From 40064f0dfecda6e404993dff056e7a666cca7d26 Mon Sep 17 00:00:00 2001 From: amit-momin <108959691+amit-momin@users.noreply.github.com> Date: Wed, 17 Apr 2024 12:06:44 -0500 Subject: [PATCH 01/26] Update TXM method signature to match TX ID type (#12851) * Updated TXM method signature to match TX ID type * Fixed linting --- .changeset/weak-emus-reply.md | 5 +++++ common/txmgr/mocks/tx_manager.go | 8 +++---- common/txmgr/txmgr.go | 6 +++--- common/txmgr/types/mocks/tx_store.go | 8 +++---- common/txmgr/types/tx_store.go | 2 +- core/chains/evm/txmgr/evm_tx_store.go | 2 +- core/chains/evm/txmgr/evm_tx_store_test.go | 23 +++++++++++++++++++++ core/chains/evm/txmgr/mocks/evm_tx_store.go | 8 +++---- 8 files changed, 45 insertions(+), 17 deletions(-) create mode 100644 .changeset/weak-emus-reply.md diff --git a/.changeset/weak-emus-reply.md b/.changeset/weak-emus-reply.md new file mode 100644 index 00000000000..ef0c1fe4dae --- /dev/null +++ b/.changeset/weak-emus-reply.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Updated FindTxesWithAttemptsAndReceiptsByIdsAndState method signature to accept int64 for tx ID instead of big.Int diff --git a/common/txmgr/mocks/tx_manager.go b/common/txmgr/mocks/tx_manager.go index 37b0822941d..a5f05219217 100644 --- a/common/txmgr/mocks/tx_manager.go +++ b/common/txmgr/mocks/tx_manager.go @@ -184,7 +184,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } // FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID -func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { +func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { ret := _m.Called(ctx, ids, states, chainID) if len(ret) == 0 { @@ -193,10 +193,10 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { return rf(ctx, ids, states, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { r0 = rf(ctx, ids, states, chainID) } else { if ret.Get(0) != nil { @@ -204,7 +204,7 @@ func (_m *TxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTx } } - if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) error); ok { r1 = rf(ctx, ids, states, chainID) } else { r1 = ret.Error(1) diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index b996b76f1a5..39895941ffd 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -57,7 +57,7 @@ type TxManager[ // Find transactions with a non-null TxMeta field that was provided and a receipt block number greater than or equal to the one provided FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) // Find transactions loaded with transaction attempts and receipts by transaction IDs and states - FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) FindEarliestUnconfirmedBroadcastTime(ctx context.Context) (nullv4.Time, error) FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context) (nullv4.Int, error) CountTransactionsByState(ctx context.Context, state txmgrtypes.TxState) (count uint32, err error) @@ -587,7 +587,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWi return } -func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { +func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { txes, err = b.txStore.FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx, ids, states, chainID) return } @@ -667,7 +667,7 @@ func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) Fin func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { return txes, errors.New(n.ErrMsg) } -func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { +func (n *NullTxManager[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) (txes []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) { return txes, errors.New(n.ErrMsg) } diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index 814207d3986..8d70fe6b5a9 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -551,7 +551,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesPen } // FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { ret := _m.Called(ctx, ids, states, chainID) if len(ret) == 0 { @@ -560,10 +560,10 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWit var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { return rf(ctx, ids, states, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { r0 = rf(ctx, ids, states, chainID) } else { if ret.Get(0) != nil { @@ -571,7 +571,7 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxesWit } } - if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []txmgrtypes.TxState, *big.Int) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, []int64, []txmgrtypes.TxState, *big.Int) error); ok { r1 = rf(ctx, ids, states, chainID) } else { r1 = ret.Error(1) diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index f061f0ea628..43d41cb4d31 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -52,7 +52,7 @@ type TxStore[ // Find transactions with a non-null TxMeta field that was provided and a receipt block number greater than or equal to the one provided FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, metaField string, blockNum int64, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) // Find transactions loaded with transaction attempts and receipts by transaction IDs and states - FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []TxState, chainID *big.Int) (tx []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) } // TransactionStore contains the persistence layer methods needed to manage Txs and TxAttempts diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 55f650e934b..7a05f32c9e4 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1939,7 +1939,7 @@ func (o *evmTxStore) FindTxesWithMetaFieldByReceiptBlockNum(ctx context.Context, } // Find transactions loaded with transaction attempts and receipts by transaction IDs and states -func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []txmgrtypes.TxState, chainID *big.Int) (txes []*Tx, err error) { +func (o *evmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []txmgrtypes.TxState, chainID *big.Int) (txes []*Tx, err error) { var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 6cfc01c20d0..5d3fdcfafd8 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -1858,6 +1858,29 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { }) } +func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) { + t.Parallel() + + db := pgtest.NewSqlxDB(t) + cfg := configtest.NewGeneralConfig(t, nil) + txStore := cltest.NewTestTxStore(t, db) + ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ctx := testutils.Context(t) + + _, from := cltest.MustInsertRandomKey(t, ethKeyStore) + + tx := cltest.MustInsertConfirmedEthTxWithLegacyAttempt(t, txStore, 0, 1, from) + r := newEthReceipt(4, utils.NewHash(), tx.TxAttempts[0].Hash, 0x1) + _, err := txStore.InsertReceipt(ctx, &r.Receipt) + require.NoError(t, err) + + txes, err := txStore.FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx, []int64{tx.ID}, []txmgrtypes.TxState{txmgrcommon.TxConfirmed}, testutils.FixtureChainID) + require.NoError(t, err) + require.Len(t, txes, 1) + require.Len(t, txes[0].TxAttempts, 1) + require.Len(t, txes[0].TxAttempts[0].Receipts, 1) +} + func AssertCountPerSubject(t *testing.T, txStore txmgr.TestEvmTxStore, expected int64, subject uuid.UUID) { t.Helper() count, err := txStore.CountTxesByStateAndSubject(testutils.Context(t), "unstarted", subject) diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index 61c948c1ff4..b6806f34d76 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -672,7 +672,7 @@ func (_m *EvmTxStore) FindTxesPendingCallback(ctx context.Context, blockNum int6 } // FindTxesWithAttemptsAndReceiptsByIdsAndState provides a mock function with given fields: ctx, ids, states, chainID -func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []big.Int, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { +func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.Context, ids []int64, states []types.TxState, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { ret := _m.Called(ctx, ids, states, chainID) if len(ret) == 0 { @@ -681,10 +681,10 @@ func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.C var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []types.TxState, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { return rf(ctx, ids, states, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, []big.Int, []types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + if rf, ok := ret.Get(0).(func(context.Context, []int64, []types.TxState, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { r0 = rf(ctx, ids, states, chainID) } else { if ret.Get(0) != nil { @@ -692,7 +692,7 @@ func (_m *EvmTxStore) FindTxesWithAttemptsAndReceiptsByIdsAndState(ctx context.C } } - if rf, ok := ret.Get(1).(func(context.Context, []big.Int, []types.TxState, *big.Int) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, []int64, []types.TxState, *big.Int) error); ok { r1 = rf(ctx, ids, states, chainID) } else { r1 = ret.Error(1) From 2f60dbee54b3e17dd6caad7dbc9bd14ff71c843b Mon Sep 17 00:00:00 2001 From: Tate Date: Wed, 17 Apr 2024 11:36:18 -0600 Subject: [PATCH 02/26] Fix e2e test log artifact name collision on upload (#12861) --- .github/workflows/integration-tests.yml | 25 ++++++++----------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 1386bfef8f3..98d67a8b2d3 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -379,6 +379,7 @@ jobs: cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ inputs.evm-ref || github.sha }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: ${{ matrix.product.name }}-test-logs artifacts_location: | ./integration-tests/smoke/logs/ /tmp/gotest.log @@ -470,6 +471,7 @@ jobs: cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ inputs.evm-ref || github.sha }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: ${{ matrix.product.name }}-test-logs artifacts_location: | ./integration-tests/smoke/logs/ /tmp/gotest.log @@ -854,6 +856,7 @@ jobs: test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ steps.get_latest_version.outputs.latest_version }} + artifacts_name: node-migration-test-logs artifacts_location: | ./integration-tests/migration/logs /tmp/gotest.log @@ -865,14 +868,6 @@ jobs: QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: ${{ secrets.QA_KUBECONFIG }} - - name: Upload test log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: failure() - with: - name: test-log-${{ matrix.product.name }} - path: /tmp/gotest.log - retention-days: 7 - continue-on-error: true - name: Collect Metrics if: always() id: collect-gha-metrics @@ -1160,21 +1155,17 @@ jobs: test_command_to_run: export ENV_JOB_IMAGE=${{ secrets.QA_AWS_ACCOUNT_NUMBER }}.dkr.ecr.${{ secrets.QA_AWS_REGION }}.amazonaws.com/chainlink-solana-tests:${{ needs.get_solana_sha.outputs.sha }} && make test_smoke cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ inputs.evm-ref || github.sha }} - artifacts_location: /home/runner/work/chainlink-solana/chainlink-solana/integration-tests/logs publish_check_name: Solana Smoke Test Results go_mod_path: ./integration-tests/go.mod cache_key_id: core-solana-e2e-${{ env.MOD_CACHE_VERSION }} token: ${{ secrets.GITHUB_TOKEN }} aws_registries: ${{ secrets.QA_AWS_ACCOUNT_NUMBER }} + artifacts_name: solana-test-logs + artifacts_location: | + ./integration-tests/smoke/logs + /tmp/gotest.log QA_AWS_REGION: ${{ secrets.QA_AWS_REGION }} QA_AWS_ROLE_TO_ASSUME: ${{ secrets.QA_AWS_ROLE_TO_ASSUME }} QA_KUBECONFIG: "" run_setup: false - - name: Upload test log - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - if: failure() - with: - name: test-log-solana - path: /tmp/gotest.log - retention-days: 7 - continue-on-error: true + From b468bc961941cbbfa5de980a970f6c6a35365d7f Mon Sep 17 00:00:00 2001 From: Austin Born Date: Wed, 17 Apr 2024 12:54:27 -0700 Subject: [PATCH 03/26] Update CODEOWNERS for OperatorForwarder contracts (#12868) --- CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CODEOWNERS b/CODEOWNERS index 65f0b58753f..8741cb7a685 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -75,7 +75,7 @@ core/scripts/gateway @smartcontractkit/functions /contracts/src/v0.8/l2ep @chris-de-leon-cll /contracts/src/v0.8/llo-feeds @smartcontractkit/mercury-team # TODO: mocks folder, folder should be removed and files moved to the correct folders -/contracts/src/v0.8/operatorforwarder @RensR +/contracts/src/v0.8/operatorforwarder @austinborn /contracts/src/v0.8/shared @RensR # TODO: tests folder, folder should be removed and files moved to the correct folders # TODO: transmission folder, owner should be found From ccb8cd85fef8e3bbe3fb5580277a7bd7f477e6bb Mon Sep 17 00:00:00 2001 From: Dylan Tinianov Date: Wed, 17 Apr 2024 16:09:25 -0400 Subject: [PATCH 04/26] Fix and re-enable abandoned tx tracker (#12533) * Re-enable tracker * generate * update tracker * fix race conditions * Update tracker.go * Update tracker.go * Ensure thread safety * Update tracker.go * concurrently track txes * Optimizations * update logging * Update tracker.go * Update CHANGELOG.md * Update common/txmgr/tracker.go Co-authored-by: Jim W * GetAbandonedTransactions * lint * enabled address check * Update tracker_test.go * Update tracker.go * Ignore confirmed txes * Don't resend abandoned txes * Remove comment * Update tracker_test.go * Remove unused block height * changeset * Update tracker_test.go --------- Co-authored-by: Jim W Co-authored-by: Prashant Yadav <34992934+prashantkumar1982@users.noreply.github.com> --- .changeset/gold-bottles-tell.md | 5 + common/txmgr/resender.go | 3 - common/txmgr/tracker.go | 257 ++++++++++---------- common/txmgr/txmgr.go | 43 ++-- common/txmgr/types/mocks/tx_store.go | 48 ++-- common/txmgr/types/tx_store.go | 2 +- core/chains/evm/txmgr/evm_tx_store.go | 34 +-- core/chains/evm/txmgr/evm_tx_store_test.go | 39 ++- core/chains/evm/txmgr/mocks/evm_tx_store.go | 48 ++-- core/chains/evm/txmgr/tracker_test.go | 48 ++-- 10 files changed, 276 insertions(+), 251 deletions(-) create mode 100644 .changeset/gold-bottles-tell.md diff --git a/.changeset/gold-bottles-tell.md b/.changeset/gold-bottles-tell.md new file mode 100644 index 00000000000..5289f368a55 --- /dev/null +++ b/.changeset/gold-bottles-tell.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#added : Re-enable abandoned transaction tracker diff --git a/common/txmgr/resender.go b/common/txmgr/resender.go index 8c2dd6b827e..b752ec63f13 100644 --- a/common/txmgr/resender.go +++ b/common/txmgr/resender.go @@ -140,9 +140,6 @@ func (er *Resender[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) resendUnco return fmt.Errorf("Resender failed getting enabled keys for chain %s: %w", er.chainID.String(), err) } - // Tracker currently disabled for BCI-2638; refactor required - // resendAddresses = append(resendAddresses, er.tracker.GetAbandonedAddresses()...) - ageThreshold := er.txConfig.ResendAfterThreshold() maxInFlightTransactions := er.txConfig.MaxInFlight() olderThan := time.Now().Add(-ageThreshold) diff --git a/common/txmgr/tracker.go b/common/txmgr/tracker.go index c63d9c264fc..a7236472710 100644 --- a/common/txmgr/tracker.go +++ b/common/txmgr/tracker.go @@ -8,6 +8,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" @@ -22,17 +23,10 @@ const ( // handleTxesTimeout represents a sanity limit on how long handleTxesByState // should take to complete handleTxesTimeout = 10 * time.Minute + // batchSize is the number of txes to fetch from the txStore at once + batchSize = 1000 ) -// AbandonedTx is a transaction who's 'FromAddress' was removed from the KeyStore(by the Node Operator). -// Thus, any new attempts for this Tx can't be signed/created. This means no fee bumping can be done. -// However, the Tx may still have live attempts in the chain's mempool, and could get confirmed on the -// chain as-is. Thus, the TXM should not directly discard this Tx. -type AbandonedTx[ADDR types.Hashable] struct { - id int64 - fromAddress ADDR -} - // Tracker tracks all transactions which have abandoned fromAddresses. // The fromAddresses can be deleted by Node Operators from the KeyStore. In such cases, // existing in-flight transactions for these fromAddresses are considered abandoned too. @@ -48,19 +42,22 @@ type Tracker[ FEE feetypes.Fee, ] struct { services.StateMachine - txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] - keyStore txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ] - chainID CHAIN_ID - lggr logger.Logger - enabledAddrs map[ADDR]bool - txCache map[int64]AbandonedTx[ADDR] - ttl time.Duration + txStore txmgrtypes.TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE] + keyStore txmgrtypes.KeyStore[ADDR, CHAIN_ID, SEQ] + chainID CHAIN_ID + lggr logger.Logger + lock sync.Mutex - mb *mailbox.Mailbox[int64] - wg sync.WaitGroup - isStarted bool - ctx context.Context - ctxCancel context.CancelFunc + enabledAddrs map[ADDR]bool + txCache map[int64]ADDR // cache tx fromAddress by txID + + ttl time.Duration + mb *mailbox.Mailbox[int64] + + initSync sync.Mutex + wg sync.WaitGroup + chStop services.StopChan + isStarted bool } func NewTracker[ @@ -83,7 +80,7 @@ func NewTracker[ chainID: chainID, lggr: logger.Named(lggr, "TxMgrTracker"), enabledAddrs: map[ADDR]bool{}, - txCache: map[int64]AbandonedTx[ADDR]{}, + txCache: map[int64]ADDR{}, ttl: defaultTTL, mb: mailbox.NewSingle[int64](), lock: sync.Mutex{}, @@ -99,75 +96,84 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Start(ctx c } func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) startInternal(ctx context.Context) (err error) { - tr.lock.Lock() - defer tr.lock.Unlock() - - tr.ctx, tr.ctxCancel = context.WithCancel(context.Background()) + tr.initSync.Lock() + defer tr.initSync.Unlock() if err := tr.setEnabledAddresses(ctx); err != nil { return fmt.Errorf("failed to set enabled addresses: %w", err) } - tr.lggr.Info("Enabled addresses set") + tr.lggr.Infof("enabled addresses set for chainID %v", tr.chainID) - if err := tr.trackAbandonedTxes(ctx); err != nil { - return fmt.Errorf("failed to track abandoned txes: %w", err) - } - - tr.isStarted = true - if len(tr.txCache) == 0 { - tr.lggr.Info("no abandoned txes found, skipping runLoop") - return nil - } - - tr.lggr.Infof("%d abandoned txes found, starting runLoop", len(tr.txCache)) + tr.chStop = make(chan struct{}) tr.wg.Add(1) - go tr.runLoop() + go tr.runLoop(tr.chStop.NewCtx()) + tr.isStarted = true return nil } func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Close() error { - tr.lock.Lock() - defer tr.lock.Unlock() return tr.StopOnce("Tracker", func() error { return tr.closeInternal() }) } func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) closeInternal() error { + tr.initSync.Lock() + defer tr.initSync.Unlock() + tr.lggr.Info("stopping tracker") if !tr.isStarted { - return fmt.Errorf("tracker not started") + return fmt.Errorf("tracker is not started: %w", services.ErrAlreadyStopped) } - tr.ctxCancel() + + close(tr.chStop) tr.wg.Wait() tr.isStarted = false return nil } -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() { +func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop(ctx context.Context, cancel context.CancelFunc) { defer tr.wg.Done() + defer cancel() + + if err := tr.trackAbandonedTxes(ctx); err != nil { + tr.lggr.Errorf("failed to track abandoned txes: %v", err) + return + } + if err := tr.handleTxesByState(ctx); err != nil { + tr.lggr.Errorf("failed to handle txes by state: %v", err) + return + } + if tr.AbandonedTxCount() == 0 { + tr.lggr.Info("no abandoned txes found, skipping runLoop") + return + } + tr.lggr.Infof("%d abandoned txes found, starting runLoop", tr.AbandonedTxCount()) + ttlExceeded := time.NewTicker(tr.ttl) defer ttlExceeded.Stop() for { select { case <-tr.mb.Notify(): for { - if tr.ctx.Err() != nil { - return - } - blockHeight, exists := tr.mb.Retrieve() - if !exists { + blockHeight := tr.mb.RetrieveLatestAndClear() + if blockHeight == 0 { break } - if err := tr.HandleTxesByState(tr.ctx, blockHeight); err != nil { - tr.lggr.Errorw(fmt.Errorf("failed to handle txes by state: %w", err).Error()) + if err := tr.handleTxesByState(ctx); err != nil { + tr.lggr.Errorf("failed to handle txes by state: %v", err) + return + } + if tr.AbandonedTxCount() == 0 { + tr.lggr.Info("all abandoned txes handled, stopping runLoop") + return } } case <-ttlExceeded.C: tr.lggr.Info("ttl exceeded") - tr.MarkAllTxesFatal(tr.ctx) + tr.markAllTxesFatal(ctx) return - case <-tr.ctx.Done(): + case <-ctx.Done(): return } } @@ -177,24 +183,31 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetAbandone tr.lock.Lock() defer tr.lock.Unlock() - if !tr.isStarted { - return []ADDR{} - } - abandonedAddrs := make([]ADDR, len(tr.txCache)) - for _, atx := range tr.txCache { - abandonedAddrs = append(abandonedAddrs, atx.fromAddress) + for _, fromAddress := range tr.txCache { + abandonedAddrs = append(abandonedAddrs, fromAddress) } return abandonedAddrs } -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) IsStarted() bool { +// AbandonedTxCount returns the number of abandoned txes currently being tracked +func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) AbandonedTxCount() int { tr.lock.Lock() defer tr.lock.Unlock() + return len(tr.txCache) +} + +func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) IsStarted() bool { + tr.initSync.Lock() + defer tr.initSync.Unlock() return tr.isStarted } +// setEnabledAddresses is called on startup to set the enabled addresses for the chain func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) setEnabledAddresses(ctx context.Context) error { + tr.lock.Lock() + defer tr.lock.Unlock() + enabledAddrs, err := tr.keyStore.EnabledAddressesForChain(ctx, tr.chainID) if err != nil { return fmt.Errorf("failed to get enabled addresses for chain: %w", err) @@ -210,54 +223,58 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) setEnabledA return nil } -// trackAbandonedTxes called once to find and insert all abandoned txes into the tracker. +// trackAbandonedTxes called on startup to find and insert all abandoned txes into the tracker. func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) trackAbandonedTxes(ctx context.Context) (err error) { - if tr.isStarted { - return fmt.Errorf("tracker already started") - } - - tr.lggr.Info("Retrieving non fatal transactions from txStore") - nonFatalTxes, err := tr.txStore.GetNonFatalTransactions(ctx, tr.chainID) - if err != nil { - return fmt.Errorf("failed to get non fatal txes from txStore: %w", err) - } - - // insert abandoned txes - for _, tx := range nonFatalTxes { - if !tr.enabledAddrs[tx.FromAddress] { - tr.insertTx(tx) + return sqlutil.Batch(func(offset, limit uint) (count uint, err error) { + var enabledAddrs []ADDR + for addr := range tr.enabledAddrs { + enabledAddrs = append(enabledAddrs, addr) } - } - if err := tr.handleTxesByState(ctx, 0); err != nil { - return fmt.Errorf("failed to handle txes by state: %w", err) - } - - return nil + nonFatalTxes, err := tr.txStore.GetAbandonedTransactionsByBatch(ctx, tr.chainID, enabledAddrs, offset, limit) + if err != nil { + return 0, fmt.Errorf("failed to get non fatal txes from txStore: %w", err) + } + // insert abandoned txes + tr.lock.Lock() + for _, tx := range nonFatalTxes { + if !tr.enabledAddrs[tx.FromAddress] { + tr.txCache[tx.ID] = tx.FromAddress + tr.lggr.Debugf("inserted tx %v", tx.ID) + } + } + tr.lock.Unlock() + return uint(len(nonFatalTxes)), nil + }, batchSize) } -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) HandleTxesByState(ctx context.Context, blockHeight int64) error { +// handleTxesByState handles all txes in the txCache by their state +// It's called on every new blockHeight and also on startup to handle all txes in the txCache +func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleTxesByState(ctx context.Context) error { tr.lock.Lock() defer tr.lock.Unlock() - tr.ctx, tr.ctxCancel = context.WithTimeout(ctx, handleTxesTimeout) - defer tr.ctxCancel() - return tr.handleTxesByState(ctx, blockHeight) -} + ctx, cancel := context.WithTimeout(ctx, handleTxesTimeout) + defer cancel() -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleTxesByState(ctx context.Context, blockHeight int64) error { - tr.lggr.Info("Handling transactions by state") + for id := range tr.txCache { + if ctx.Err() != nil { + return ctx.Err() + } - for id, atx := range tr.txCache { - tx, err := tr.txStore.GetTxByID(ctx, atx.id) + tx, err := tr.txStore.GetTxByID(ctx, id) if err != nil { - return fmt.Errorf("failed to get tx by ID: %w", err) + tr.lggr.Errorf("failed to get tx by ID: %v", err) + continue + } + if tx == nil { + tr.lggr.Warnf("tx with ID %v no longer exists, removing from tracker", id) + delete(tr.txCache, id) + continue } switch tx.State { case TxConfirmed: - if err := tr.handleConfirmedTx(tx, blockHeight); err != nil { - return fmt.Errorf("failed to handle confirmed txes: %w", err) - } + // TODO: Handle finalized state https://smartcontract-it.atlassian.net/browse/BCI-2920 case TxConfirmedMissingReceipt, TxUnconfirmed: // Keep tracking tx case TxInProgress, TxUnstarted: @@ -266,50 +283,20 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleTxesB // is deleted, we can't sign it. errMsg := "The FromAddress for this Tx was deleted before this Tx could be broadcast to the chain." if err := tr.markTxFatal(ctx, tx, errMsg); err != nil { - return fmt.Errorf("failed to mark tx as fatal: %w", err) + tr.lggr.Errorf("failed to mark tx as fatal: %v", err) + continue } delete(tr.txCache, id) case TxFatalError: delete(tr.txCache, id) default: - tr.lggr.Errorw(fmt.Sprintf("unhandled transaction state: %v", tx.State)) + tr.lggr.Errorf("unhandled transaction state: %v", tx.State) } } return nil } -// handleConfirmedTx removes a transaction from the tracker if it's been finalized on chain -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) handleConfirmedTx( - tx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], - blockHeight int64, -) error { - finalized, err := tr.txStore.IsTxFinalized(tr.ctx, blockHeight, tx.ID, tr.chainID) - if err != nil { - return fmt.Errorf("failed to check if tx is finalized: %w", err) - } - - if finalized { - delete(tr.txCache, tx.ID) - } - - return nil -} - -// insertTx inserts a transaction into the tracker as an AbandonedTx -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) insertTx( - tx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) { - if _, contains := tr.txCache[tx.ID]; contains { - return - } - - tr.txCache[tx.ID] = AbandonedTx[ADDR]{ - id: tx.ID, - fromAddress: tx.FromAddress, - } - tr.lggr.Debugw(fmt.Sprintf("inserted tx %v", tx.ID)) -} - func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) markTxFatal(ctx context.Context, tx *txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], errMsg string) error { @@ -323,22 +310,26 @@ func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) markTxFatal return nil } -func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) MarkAllTxesFatal(ctx context.Context) { +// markAllTxesFatal tries to mark all txes in the txCache as fatal and removes them from the cache +func (tr *Tracker[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) markAllTxesFatal(ctx context.Context) { tr.lock.Lock() defer tr.lock.Unlock() + errMsg := fmt.Sprintf( - "fromAddress for this Tx was deleted, and existing attempts onchain didn't finalize within %d hours, thus this Tx was abandoned.", + "tx abandoned: fromAddress for this tx was deleted and existing attempts didn't finalize onchain within %d hours", int(tr.ttl.Hours())) - for _, atx := range tr.txCache { - tx, err := tr.txStore.GetTxByID(ctx, atx.id) + for id := range tr.txCache { + tx, err := tr.txStore.GetTxByID(ctx, id) if err != nil { - tr.lggr.Errorw(fmt.Errorf("failed to get tx by ID: %w", err).Error()) + tr.lggr.Errorf("failed to get tx by ID: %v", err) + delete(tr.txCache, id) continue } if err := tr.markTxFatal(ctx, tx, errMsg); err != nil { - tr.lggr.Errorw(fmt.Errorf("failed to mark tx as abandoned: %w", err).Error()) + tr.lggr.Errorf("failed to mark tx as abandoned: %v", err) } + delete(tr.txCache, id) } } diff --git a/common/txmgr/txmgr.go b/common/txmgr/txmgr.go index 39895941ffd..4d4eabe5c40 100644 --- a/common/txmgr/txmgr.go +++ b/common/txmgr/txmgr.go @@ -190,12 +190,9 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Start(ctx return fmt.Errorf("Txm: Estimator failed to start: %w", err) } - /* Tracker currently disabled for BCI-2638; refactor required - b.logger.Info("Txm starting tracker") if err := ms.Start(ctx, b.tracker); err != nil { return fmt.Errorf("Txm: Tracker failed to start: %w", err) } - */ b.logger.Info("Txm starting runLoop") b.wg.Add(1) @@ -275,12 +272,6 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) Close() (m merr = errors.Join(merr, fmt.Errorf("Txm: failed to close TxAttemptBuilder: %w", err)) } - /* Tracker currently disabled for BCI-2638; refactor required - if err := b.tracker.Close(); err != nil { - merr = errors.Join(merr, fmt.Errorf("Txm: failed to close Tracker: %w", err)) - } - */ - return nil }) } @@ -329,6 +320,9 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() if err := b.broadcaster.closeInternal(); err != nil { b.logger.Panicw(fmt.Sprintf("Failed to Close Broadcaster: %v", err), "err", err) } + if err := b.tracker.closeInternal(); err != nil { + b.logger.Panicw(fmt.Sprintf("Failed to Close Tracker: %v", err), "err", err) + } if err := b.confirmer.closeInternal(); err != nil { b.logger.Panicw(fmt.Sprintf("Failed to Close Confirmer: %v", err), "err", err) } @@ -337,16 +331,17 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() close(r.done) } var wg sync.WaitGroup - // two goroutines to handle independent backoff retries starting: + // three goroutines to handle independent backoff retries starting: // - Broadcaster // - Confirmer + // - Tracker // If chStop is closed, we mark stopped=true so that the main runloop // can check and exit early if necessary // // execReset will not return until either: - // 1. Both Broadcaster and Confirmer started successfully + // 1. Broadcaster, Confirmer, and Tracker all started successfully // 2. chStop was closed (txmgr exit) - wg.Add(2) + wg.Add(3) go func() { defer wg.Done() // Retry indefinitely on failure @@ -366,6 +361,25 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() } } }() + go func() { + defer wg.Done() + // Retry indefinitely on failure + backoff := iutils.NewRedialBackoff() + for { + select { + case <-time.After(backoff.Duration()): + if err := b.tracker.startInternal(ctx); err != nil { + b.logger.Criticalw("Failed to start Tracker", "err", err) + b.SvcErrBuffer.Append(err) + continue + } + return + case <-b.chStop: + stopOnce.Do(func() { stopped = true }) + return + } + } + }() go func() { defer wg.Done() // Retry indefinitely on failure @@ -395,8 +409,7 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() b.broadcaster.Trigger(address) case head := <-b.chHeads: b.confirmer.mb.Deliver(head) - // Tracker currently disabled for BCI-2638; refactor required - // b.tracker.mb.Deliver(head.BlockNumber()) + b.tracker.mb.Deliver(head.BlockNumber()) case reset := <-b.reset: // This check prevents the weird edge-case where you can select // into this block after chStop has already been closed and the @@ -424,12 +437,10 @@ func (b *Txm[CHAIN_ID, HEAD, ADDR, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) runLoop() if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { b.logger.Errorw(fmt.Sprintf("Failed to Close Confirmer: %v", err), "err", err) } - /* Tracker currently disabled for BCI-2638; refactor required err = b.tracker.Close() if err != nil && (!errors.Is(err, services.ErrAlreadyStopped) || !errors.Is(err, services.ErrCannotStopUnstarted)) { b.logger.Errorw(fmt.Sprintf("Failed to Close Tracker: %v", err), "err", err) } - */ return case <-keysChanged: // This check prevents the weird edge-case where you can select diff --git a/common/txmgr/types/mocks/tx_store.go b/common/txmgr/types/mocks/tx_store.go index 8d70fe6b5a9..64193afff5b 100644 --- a/common/txmgr/types/mocks/tx_store.go +++ b/common/txmgr/types/mocks/tx_store.go @@ -700,29 +700,29 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) FindTxsRequ return r0, r1 } -// GetInProgressTxAttempts provides a mock function with given fields: ctx, address, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetInProgressTxAttempts(ctx context.Context, address ADDR, chainID CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { - ret := _m.Called(ctx, address, chainID) +// GetAbandonedTransactionsByBatch provides a mock function with given fields: ctx, chainID, enabledAddrs, offset, limit +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetAbandonedTransactionsByBatch(ctx context.Context, chainID CHAIN_ID, enabledAddrs []ADDR, offset uint, limit uint) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { + ret := _m.Called(ctx, chainID, enabledAddrs, offset, limit) if len(ret) == 0 { - panic("no return value specified for GetInProgressTxAttempts") + panic("no return value specified for GetAbandonedTransactionsByBatch") } - var r0 []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { - return rf(ctx, address, chainID) + if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID, []ADDR, uint, uint) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + return rf(ctx, chainID, enabledAddrs, offset, limit) } - if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { - r0 = rf(ctx, address, chainID) + if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID, []ADDR, uint, uint) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + r0 = rf(ctx, chainID, enabledAddrs, offset, limit) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) + r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } } - if rf, ok := ret.Get(1).(func(context.Context, ADDR, CHAIN_ID) error); ok { - r1 = rf(ctx, address, chainID) + if rf, ok := ret.Get(1).(func(context.Context, CHAIN_ID, []ADDR, uint, uint) error); ok { + r1 = rf(ctx, chainID, enabledAddrs, offset, limit) } else { r1 = ret.Error(1) } @@ -730,29 +730,29 @@ func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetInProgre return r0, r1 } -// GetNonFatalTransactions provides a mock function with given fields: ctx, chainID -func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetNonFatalTransactions(ctx context.Context, chainID CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { - ret := _m.Called(ctx, chainID) +// GetInProgressTxAttempts provides a mock function with given fields: ctx, address, chainID +func (_m *TxStore[ADDR, CHAIN_ID, TX_HASH, BLOCK_HASH, R, SEQ, FEE]) GetInProgressTxAttempts(ctx context.Context, address ADDR, chainID CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error) { + ret := _m.Called(ctx, address, chainID) if len(ret) == 0 { - panic("no return value specified for GetNonFatalTransactions") + panic("no return value specified for GetInProgressTxAttempts") } - var r0 []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] + var r0 []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) ([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { - return rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) ([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], error)); ok { + return rf(ctx, address, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, CHAIN_ID) []*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { - r0 = rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, ADDR, CHAIN_ID) []txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]); ok { + r0 = rf(ctx, address, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*txmgrtypes.Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) + r0 = ret.Get(0).([]txmgrtypes.TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) } } - if rf, ok := ret.Get(1).(func(context.Context, CHAIN_ID) error); ok { - r1 = rf(ctx, chainID) + if rf, ok := ret.Get(1).(func(context.Context, ADDR, CHAIN_ID) error); ok { + r1 = rf(ctx, address, chainID) } else { r1 = ret.Error(1) } diff --git a/common/txmgr/types/tx_store.go b/common/txmgr/types/tx_store.go index 43d41cb4d31..bca2d1e3647 100644 --- a/common/txmgr/types/tx_store.go +++ b/common/txmgr/types/tx_store.go @@ -85,7 +85,7 @@ type TransactionStore[ FindEarliestUnconfirmedTxAttemptBlock(ctx context.Context, chainID CHAIN_ID) (null.Int, error) GetTxInProgress(ctx context.Context, fromAddress ADDR) (etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) GetInProgressTxAttempts(ctx context.Context, address ADDR, chainID CHAIN_ID) (attempts []TxAttempt[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) - GetNonFatalTransactions(ctx context.Context, chainID CHAIN_ID) (txs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) + GetAbandonedTransactionsByBatch(ctx context.Context, chainID CHAIN_ID, enabledAddrs []ADDR, offset, limit uint) (txs []*Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) GetTxByID(ctx context.Context, id int64) (tx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE], err error) HasInProgressTransaction(ctx context.Context, account ADDR, chainID CHAIN_ID) (exists bool, err error) LoadTxAttempts(ctx context.Context, etx *Tx[CHAIN_ID, ADDR, TX_HASH, BLOCK_HASH, SEQ, FEE]) error diff --git a/core/chains/evm/txmgr/evm_tx_store.go b/core/chains/evm/txmgr/evm_tx_store.go index 7a05f32c9e4..c8e664e8cfe 100644 --- a/core/chains/evm/txmgr/evm_tx_store.go +++ b/core/chains/evm/txmgr/evm_tx_store.go @@ -1292,26 +1292,28 @@ func (o *evmTxStore) SaveInProgressAttempt(ctx context.Context, attempt *TxAttem return nil } -func (o *evmTxStore) GetNonFatalTransactions(ctx context.Context, chainID *big.Int) (txes []*Tx, err error) { +func (o *evmTxStore) GetAbandonedTransactionsByBatch(ctx context.Context, chainID *big.Int, enabledAddrs []common.Address, offset, limit uint) (txes []*Tx, err error) { var cancel context.CancelFunc ctx, cancel = o.mergeContexts(ctx) defer cancel() - err = o.Transaction(ctx, true, func(orm *evmTxStore) error { - stmt := `SELECT * FROM evm.txes WHERE state <> 'fatal_error' AND evm_chain_id = $1` - var dbEtxs []DbEthTx - if err = orm.q.SelectContext(ctx, &dbEtxs, stmt, chainID.String()); err != nil { - return fmt.Errorf("failed to load evm.txes: %w", err) - } - txes = make([]*Tx, len(dbEtxs)) - dbEthTxsToEvmEthTxPtrs(dbEtxs, txes) - err = o.LoadTxesAttempts(ctx, txes) - if err != nil { - return fmt.Errorf("failed to load evm.txes: %w", err) - } - return nil - }) - return txes, nil + var enabledAddrsBytea [][]byte + for _, addr := range enabledAddrs { + enabledAddrsBytea = append(enabledAddrsBytea, addr[:]) + } + + // TODO: include confirmed txes https://smartcontract-it.atlassian.net/browse/BCI-2920 + query := `SELECT * FROM evm.txes WHERE state <> 'fatal_error' AND state <> 'confirmed' AND evm_chain_id = $1 + AND from_address <> ALL($2) ORDER BY nonce ASC OFFSET $3 LIMIT $4` + + var dbEtxs []DbEthTx + if err = o.q.SelectContext(ctx, &dbEtxs, query, chainID.String(), enabledAddrsBytea, offset, limit); err != nil { + return nil, fmt.Errorf("failed to load evm.txes: %w", err) + } + txes = make([]*Tx, len(dbEtxs)) + dbEthTxsToEvmEthTxPtrs(dbEtxs, txes) + + return txes, err } func (o *evmTxStore) GetTxByID(ctx context.Context, id int64) (txe *Tx, err error) { diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index 5d3fdcfafd8..ff5c7ec4abc 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -7,6 +7,8 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/common" + commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" @@ -1470,7 +1472,7 @@ func TestORM_GetTxInProgress(t *testing.T) { }) } -func TestORM_GetNonFatalTransactions(t *testing.T) { +func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) @@ -1479,9 +1481,19 @@ func TestORM_GetNonFatalTransactions(t *testing.T) { ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + _, enabled := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) + enabledAddrs := []common.Address{enabled} + + t.Run("get 0 abandoned transactions", func(t *testing.T) { + txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) + require.NoError(t, err) + require.Empty(t, txes) + }) - t.Run("gets 0 non finalized eth transaction", func(t *testing.T) { - txes, err := txStore.GetNonFatalTransactions(testutils.Context(t), ethClient.ConfiguredChainID()) + t.Run("do not return enabled addresses", func(t *testing.T) { + _ = mustInsertInProgressEthTxWithAttempt(t, txStore, 123, enabled) + _ = mustCreateUnstartedGeneratedTx(t, txStore, enabled, ethClient.ConfiguredChainID()) + txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) require.NoError(t, err) require.Empty(t, txes) }) @@ -1490,13 +1502,32 @@ func TestORM_GetNonFatalTransactions(t *testing.T) { inProgressTx := mustInsertInProgressEthTxWithAttempt(t, txStore, 123, fromAddress) unstartedTx := mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, ethClient.ConfiguredChainID()) - txes, err := txStore.GetNonFatalTransactions(testutils.Context(t), ethClient.ConfiguredChainID()) + txes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, 0, 10) require.NoError(t, err) + require.Len(t, txes, 2) for _, tx := range txes { require.True(t, tx.ID == inProgressTx.ID || tx.ID == unstartedTx.ID) } }) + + t.Run("get batches of transactions", func(t *testing.T) { + var batchSize uint = 10 + numTxes := 55 + for i := 0; i < numTxes; i++ { + _ = mustCreateUnstartedGeneratedTx(t, txStore, fromAddress, ethClient.ConfiguredChainID()) + } + + allTxes := make([]*txmgr.Tx, 0) + err := sqlutil.Batch(func(offset, limit uint) (count uint, err error) { + batchTxes, err := txStore.GetAbandonedTransactionsByBatch(testutils.Context(t), ethClient.ConfiguredChainID(), enabledAddrs, offset, limit) + require.NoError(t, err) + allTxes = append(allTxes, batchTxes...) + return uint(len(batchTxes)), nil + }, batchSize) + require.NoError(t, err) + require.Len(t, allTxes, numTxes+2) + }) } func TestORM_GetTxByID(t *testing.T) { diff --git a/core/chains/evm/txmgr/mocks/evm_tx_store.go b/core/chains/evm/txmgr/mocks/evm_tx_store.go index b6806f34d76..a05f2a22c60 100644 --- a/core/chains/evm/txmgr/mocks/evm_tx_store.go +++ b/core/chains/evm/txmgr/mocks/evm_tx_store.go @@ -821,29 +821,29 @@ func (_m *EvmTxStore) FindTxsRequiringResubmissionDueToInsufficientFunds(ctx con return r0, r1 } -// GetInProgressTxAttempts provides a mock function with given fields: ctx, address, chainID -func (_m *EvmTxStore) GetInProgressTxAttempts(ctx context.Context, address common.Address, chainID *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { - ret := _m.Called(ctx, address, chainID) +// GetAbandonedTransactionsByBatch provides a mock function with given fields: ctx, chainID, enabledAddrs, offset, limit +func (_m *EvmTxStore) GetAbandonedTransactionsByBatch(ctx context.Context, chainID *big.Int, enabledAddrs []common.Address, offset uint, limit uint) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { + ret := _m.Called(ctx, chainID, enabledAddrs, offset, limit) if len(ret) == 0 { - panic("no return value specified for GetInProgressTxAttempts") + panic("no return value specified for GetAbandonedTransactionsByBatch") } - var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] + var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { - return rf(ctx, address, chainID) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, []common.Address, uint, uint) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + return rf(ctx, chainID, enabledAddrs, offset, limit) } - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { - r0 = rf(ctx, address, chainID) + if rf, ok := ret.Get(0).(func(context.Context, *big.Int, []common.Address, uint, uint) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + r0 = rf(ctx, chainID, enabledAddrs, offset, limit) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) + r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } - if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { - r1 = rf(ctx, address, chainID) + if rf, ok := ret.Get(1).(func(context.Context, *big.Int, []common.Address, uint, uint) error); ok { + r1 = rf(ctx, chainID, enabledAddrs, offset, limit) } else { r1 = ret.Error(1) } @@ -851,29 +851,29 @@ func (_m *EvmTxStore) GetInProgressTxAttempts(ctx context.Context, address commo return r0, r1 } -// GetNonFatalTransactions provides a mock function with given fields: ctx, chainID -func (_m *EvmTxStore) GetNonFatalTransactions(ctx context.Context, chainID *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { - ret := _m.Called(ctx, chainID) +// GetInProgressTxAttempts provides a mock function with given fields: ctx, address, chainID +func (_m *EvmTxStore) GetInProgressTxAttempts(ctx context.Context, address common.Address, chainID *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error) { + ret := _m.Called(ctx, address, chainID) if len(ret) == 0 { - panic("no return value specified for GetNonFatalTransactions") + panic("no return value specified for GetInProgressTxAttempts") } - var r0 []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] + var r0 []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee] var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) ([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { - return rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) ([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee], error)); ok { + return rf(ctx, address, chainID) } - if rf, ok := ret.Get(0).(func(context.Context, *big.Int) []*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { - r0 = rf(ctx, chainID) + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) []types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]); ok { + r0 = rf(ctx, address, chainID) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).([]*types.Tx[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) + r0 = ret.Get(0).([]types.TxAttempt[*big.Int, common.Address, common.Hash, common.Hash, evmtypes.Nonce, gas.EvmFee]) } } - if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { - r1 = rf(ctx, chainID) + if rf, ok := ret.Get(1).(func(context.Context, common.Address, *big.Int) error); ok { + r1 = rf(ctx, address, chainID) } else { r1 = ret.Error(1) } diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go index e95c005dc77..eefd89c69eb 100644 --- a/core/chains/evm/txmgr/tracker_test.go +++ b/core/chains/evm/txmgr/tracker_test.go @@ -1,7 +1,6 @@ package txmgr_test import ( - "context" "math/big" "testing" "time" @@ -10,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" @@ -44,25 +44,23 @@ func containsID(txes []*txmgr.Tx, id int64) bool { } func TestEvmTracker_Initialization(t *testing.T) { - t.Skip("BCI-2638 tracker disabled") t.Parallel() tracker, _, _, _ := newTestEvmTrackerSetup(t) + ctx := testutils.Context(t) - err := tracker.Start(context.Background()) - require.NoError(t, err) + require.NoError(t, tracker.Start(ctx)) require.True(t, tracker.IsStarted()) t.Run("stop tracker", func(t *testing.T) { - err := tracker.Close() - require.NoError(t, err) + require.NoError(t, tracker.Close()) require.False(t, tracker.IsStarted()) }) } func TestEvmTracker_AddressTracking(t *testing.T) { - t.Skip("BCI-2638 tracker disabled") t.Parallel() + ctx := testutils.Context(t) t.Run("track abandoned addresses", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -76,33 +74,37 @@ func TestEvmTracker_AddressTracking(t *testing.T) { _ = mustInsertConfirmedEthTxWithReceipt(t, txStore, confirmedAddr, 123, 1) _ = mustCreateUnstartedTx(t, txStore, unstartedAddr, cltest.MustGenerateRandomKey(t).Address, []byte{}, 0, big.Int{}, ethClient.ConfiguredChainID()) - err := tracker.Start(context.Background()) + err := tracker.Start(ctx) require.NoError(t, err) defer func(tracker *txmgr.Tracker) { err = tracker.Close() require.NoError(t, err) }(tracker) + time.Sleep(waitTime) addrs := tracker.GetAbandonedAddresses() require.NotContains(t, addrs, inProgressAddr) require.NotContains(t, addrs, unstartedAddr) - require.Contains(t, addrs, confirmedAddr) require.Contains(t, addrs, unconfirmedAddr) }) + /* TODO: finalized tx state https://smartcontract-it.atlassian.net/browse/BCI-2920 t.Run("stop tracking finalized tx", func(t *testing.T) { - t.Skip("BCI-2638 tracker disabled") tracker, txStore, _, _ := newTestEvmTrackerSetup(t) confirmedAddr := cltest.MustGenerateRandomKey(t).Address _ = mustInsertConfirmedEthTxWithReceipt(t, txStore, confirmedAddr, 123, 1) - err := tracker.Start(context.Background()) + err := tracker.Start(ctx) require.NoError(t, err) defer func(tracker *txmgr.Tracker) { err = tracker.Close() require.NoError(t, err) }(tracker) + // deliver block before minConfirmations + tracker.XXXDeliverBlock(1) + time.Sleep(waitTime) + addrs := tracker.GetAbandonedAddresses() require.Contains(t, addrs, confirmedAddr) @@ -113,26 +115,12 @@ func TestEvmTracker_AddressTracking(t *testing.T) { addrs = tracker.GetAbandonedAddresses() require.NotContains(t, addrs, confirmedAddr) }) + */ } func TestEvmTracker_ExceedingTTL(t *testing.T) { - t.Skip("BCI-2638 tracker disabled") t.Parallel() - - t.Run("confirmed but unfinalized transaction still tracked", func(t *testing.T) { - tracker, txStore, _, _ := newTestEvmTrackerSetup(t) - addr1 := cltest.MustGenerateRandomKey(t).Address - _ = mustInsertConfirmedEthTxWithReceipt(t, txStore, addr1, 123, 1) - - err := tracker.Start(context.Background()) - require.NoError(t, err) - defer func(tracker *txmgr.Tracker) { - err = tracker.Close() - require.NoError(t, err) - }(tracker) - - require.Contains(t, tracker.GetAbandonedAddresses(), addr1) - }) + ctx := testutils.Context(t) t.Run("exceeding ttl", func(t *testing.T) { tracker, txStore, _, _ := newTestEvmTrackerSetup(t) @@ -142,17 +130,17 @@ func TestEvmTracker_ExceedingTTL(t *testing.T) { tx2 := cltest.MustInsertUnconfirmedEthTx(t, txStore, 123, addr2) tracker.XXXTestSetTTL(time.Nanosecond) - err := tracker.Start(context.Background()) + err := tracker.Start(ctx) require.NoError(t, err) defer func(tracker *txmgr.Tracker) { err = tracker.Close() require.NoError(t, err) }(tracker) - time.Sleep(waitTime) + time.Sleep(100 * waitTime) require.NotContains(t, tracker.GetAbandonedAddresses(), addr1, addr2) - fatalTxes, err := txStore.GetFatalTransactions(context.Background()) + fatalTxes, err := txStore.GetFatalTransactions(ctx) require.NoError(t, err) require.True(t, containsID(fatalTxes, tx1.ID)) require.True(t, containsID(fatalTxes, tx2.ID)) From ae1f53f993c915e9ceed79a37479f9e5977099c3 Mon Sep 17 00:00:00 2001 From: Finley Decker Date: Wed, 17 Apr 2024 21:01:05 -1000 Subject: [PATCH 05/26] fix install (#12872) --- operator_ui/check.sh | 2 +- operator_ui/install.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/operator_ui/check.sh b/operator_ui/check.sh index 9e738218088..e4e12209b05 100755 --- a/operator_ui/check.sh +++ b/operator_ui/check.sh @@ -6,7 +6,7 @@ set -e # jq ^1.6 https://stedolan.github.io/jq/ repo=smartcontractkit/operator-ui -gitRoot=$(git rev-parse --show-toplevel) +gitRoot="$(dirname -- "$0")/../" cd "$gitRoot/operator_ui" tag_file=TAG diff --git a/operator_ui/install.sh b/operator_ui/install.sh index 0de72d51f4e..f86c9a2f352 100755 --- a/operator_ui/install.sh +++ b/operator_ui/install.sh @@ -4,7 +4,7 @@ set -e owner=smartcontractkit repo=operator-ui fullRepo=${owner}/${repo} -gitRoot=$(git rev-parse --show-toplevel || pwd) +gitRoot="$(dirname -- "$0")/../" cd "$gitRoot/operator_ui" unpack_dir="$gitRoot/core/web/assets" tag=$(cat TAG) From 057ef81edccbd34526f5b712f837a17082e94bc1 Mon Sep 17 00:00:00 2001 From: Lee Yik Jiun Date: Thu, 18 Apr 2024 18:16:17 +0800 Subject: [PATCH 06/26] Move vrfv2plus wrapper events from interface to implementation (#12875) --- .../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol | 20 +++++++++++++++++++ .../vrf/dev/interfaces/IVRFV2PlusWrapper.sol | 20 ------------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol index 77c225cdb02..4a806db5515 100644 --- a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol @@ -32,6 +32,26 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume LinkTokenInterface internal immutable i_link; AggregatorV3Interface internal immutable i_link_native_feed; + event FulfillmentTxSizeSet(uint32 size); + event ConfigSet( + uint32 wrapperGasOverhead, + uint32 coordinatorGasOverhead, + uint16 coordinatorGasOverheadPerWord, + uint8 coordinatorNativePremiumPercentage, + uint8 coordinatorLinkPremiumPercentage, + bytes32 keyHash, + uint8 maxNumWords, + uint32 stalenessSeconds, + int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM + ); + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + event Withdrawn(address indexed to, uint256 amount); + event NativeWithdrawn(address indexed to, uint256 amount); + event Enabled(); + event Disabled(); + error LinkAlreadySet(); error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); diff --git a/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol index 917c59433ef..85b0c47659d 100644 --- a/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol @@ -2,26 +2,6 @@ pragma solidity ^0.8.0; interface IVRFV2PlusWrapper { - event FulfillmentTxSizeSet(uint32 size); - event ConfigSet( - uint32 wrapperGasOverhead, - uint32 coordinatorGasOverhead, - uint16 coordinatorGasOverheadPerWord, - uint8 coordinatorNativePremiumPercentage, - uint8 coordinatorLinkPremiumPercentage, - bytes32 keyHash, - uint8 maxNumWords, - uint32 stalenessSeconds, - int256 fallbackWeiPerUnitLink, - uint32 fulfillmentFlatFeeNativePPM, - uint32 fulfillmentFlatFeeLinkDiscountPPM - ); - event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); - event Withdrawn(address indexed to, uint256 amount); - event NativeWithdrawn(address indexed to, uint256 amount); - event Enabled(); - event Disabled(); - /** * @return the request ID of the most recent VRF V2 request made by this wrapper. This should only * be relied option within the same transaction that the request was made. From 6991af26d9fa0e048b72a05f4f9c13f2306c0328 Mon Sep 17 00:00:00 2001 From: Silas Lenihan <32529249+silaslenihan@users.noreply.github.com> Date: Thu, 18 Apr 2024 11:23:55 -0400 Subject: [PATCH 07/26] Implement the gas estimator components refactor (#12650) * Applied LimitMultiplier to chainSpecificGasLimit in all gas estimators * Intial refactor * Revert "Applied LimitMultiplier to chainSpecificGasLimit in all gas estimators" This reverts commit e0c581c9e58a93ed64714d0b445eeffe120e4c2a. * Refactored L1GasOracle * Fixed failing tests * fixed linting issues * Updated ethClient struct to be specific to l1Oracle * Removed changes to broadcaster error handling * fixed rollup tests * Fixed remaining issues with PR * updated changesets * fixed linting issues * minor fixes * Deduplicated L1Oracle creation * Changed L1Oracle to return pointer * Update core/chains/evm/gas/rollups/arbitrum_l1_oracle.go Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com> * Added l1Oracle as a parameter to pass into gas estimators * removed casting for direct call * removed unused mocks --------- Co-authored-by: amit-momin <108959691+amit-momin@users.noreply.github.com> --- .changeset/flat-guests-marry.md | 6 + core/chains/evm/gas/arbitrum_estimator.go | 74 +-- .../chains/evm/gas/arbitrum_estimator_test.go | 119 ++--- .../chains/evm/gas/block_history_estimator.go | 14 +- .../evm/gas/block_history_estimator_test.go | 168 +++++-- core/chains/evm/gas/cmd/arbgas/main.go | 85 ---- core/chains/evm/gas/fixed_price_estimator.go | 10 +- .../evm/gas/fixed_price_estimator_test.go | 21 +- core/chains/evm/gas/mocks/eth_client.go | 61 --- core/chains/evm/gas/mocks/evm_estimator.go | 22 + .../evm/gas/mocks/fee_estimator_client.go | 154 +++++++ core/chains/evm/gas/mocks/rpc_client.go | 49 -- core/chains/evm/gas/models.go | 81 ++-- core/chains/evm/gas/models_test.go | 56 ++- .../evm/gas/rollups/arbitrum_l1_oracle.go | 300 ++++++++++++ core/chains/evm/gas/rollups/l1_oracle.go | 346 +------------- core/chains/evm/gas/rollups/l1_oracle_test.go | 92 +++- .../evm/gas/rollups/mocks/da_price_reader.go | 59 --- .../{eth_client.go => l1_oracle_client.go} | 16 +- core/chains/evm/gas/rollups/models.go | 22 - core/chains/evm/gas/rollups/op_l1_oracle.go | 431 ++++++++++++++++++ ...ce_reader_test.go => op_l1_oracle_test.go} | 18 +- .../chains/evm/gas/rollups/op_price_reader.go | 228 --------- .../evm/gas/suggested_price_estimator.go | 15 +- .../evm/gas/suggested_price_estimator_test.go | 117 +++-- core/chains/evm/txmgr/broadcaster_test.go | 18 +- core/chains/evm/txmgr/confirmer_test.go | 12 +- 27 files changed, 1443 insertions(+), 1151 deletions(-) create mode 100644 .changeset/flat-guests-marry.md delete mode 100644 core/chains/evm/gas/cmd/arbgas/main.go delete mode 100644 core/chains/evm/gas/mocks/eth_client.go create mode 100644 core/chains/evm/gas/mocks/fee_estimator_client.go delete mode 100644 core/chains/evm/gas/mocks/rpc_client.go create mode 100644 core/chains/evm/gas/rollups/arbitrum_l1_oracle.go delete mode 100644 core/chains/evm/gas/rollups/mocks/da_price_reader.go rename core/chains/evm/gas/rollups/mocks/{eth_client.go => l1_oracle_client.go} (72%) delete mode 100644 core/chains/evm/gas/rollups/models.go create mode 100644 core/chains/evm/gas/rollups/op_l1_oracle.go rename core/chains/evm/gas/rollups/{op_price_reader_test.go => op_l1_oracle_test.go} (90%) delete mode 100644 core/chains/evm/gas/rollups/op_price_reader.go diff --git a/.changeset/flat-guests-marry.md b/.changeset/flat-guests-marry.md new file mode 100644 index 00000000000..c1eb6549a96 --- /dev/null +++ b/.changeset/flat-guests-marry.md @@ -0,0 +1,6 @@ +--- +"chainlink": minor +--- + +#internal Gas Estimator L1Oracles to be chain specific +#removed cmd/arbgas diff --git a/core/chains/evm/gas/arbitrum_estimator.go b/core/chains/evm/gas/arbitrum_estimator.go index 40366c5b998..0cd4bbcdd0b 100644 --- a/core/chains/evm/gas/arbitrum_estimator.go +++ b/core/chains/evm/gas/arbitrum_estimator.go @@ -3,14 +3,10 @@ package gas import ( "context" "fmt" - "math" - "math/big" "slices" "sync" "time" - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/common" pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -19,7 +15,7 @@ import ( feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" ) type ArbConfig interface { @@ -28,11 +24,6 @@ type ArbConfig interface { BumpMin() *assets.Wei } -//go:generate mockery --quiet --name ethClient --output ./mocks/ --case=underscore --structname ETHClient -type ethClient interface { - CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) -} - // arbitrumEstimator is an Estimator which extends SuggestedPriceEstimator to use getPricesInArbGas() for gas limit estimation. type arbitrumEstimator struct { services.StateMachine @@ -40,7 +31,6 @@ type arbitrumEstimator struct { EvmEstimator // *SuggestedPriceEstimator - client ethClient pollPeriod time.Duration logger logger.Logger @@ -52,20 +42,23 @@ type arbitrumEstimator struct { chInitialised chan struct{} chStop services.StopChan chDone chan struct{} + + l1Oracle rollups.ArbL1GasOracle } -func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, rpcClient rpcClient, ethClient ethClient) EvmEstimator { +func NewArbitrumEstimator(lggr logger.Logger, cfg ArbConfig, ethClient feeEstimatorClient, l1Oracle rollups.ArbL1GasOracle) EvmEstimator { lggr = logger.Named(lggr, "ArbitrumEstimator") + return &arbitrumEstimator{ cfg: cfg, - EvmEstimator: NewSuggestedPriceEstimator(lggr, rpcClient, cfg), - client: ethClient, + EvmEstimator: NewSuggestedPriceEstimator(lggr, ethClient, cfg, l1Oracle), pollPeriod: 10 * time.Second, logger: lggr, chForceRefetch: make(chan (chan struct{})), chInitialised: make(chan struct{}), chStop: make(chan struct{}), chDone: make(chan struct{}), + l1Oracle: l1Oracle, } } @@ -196,7 +189,7 @@ func (a *arbitrumEstimator) run() { func (a *arbitrumEstimator) refreshPricesInArbGas() (t *time.Timer) { t = time.NewTimer(utils.WithJitter(a.pollPeriod)) - perL2Tx, perL1CalldataUnit, err := a.callGetPricesInArbGas() + perL2Tx, perL1CalldataUnit, err := a.l1Oracle.GetPricesInArbGas() if err != nil { a.logger.Warnw("Failed to refresh prices", "err", err) return @@ -210,54 +203,3 @@ func (a *arbitrumEstimator) refreshPricesInArbGas() (t *time.Timer) { a.getPricesInArbGasMu.Unlock() return } - -const ( - // ArbGasInfoAddress is the address of the "Precompiled contract that exists in every Arbitrum chain." - // https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol - ArbGasInfoAddress = "0x000000000000000000000000000000000000006C" - // ArbGasInfo_getPricesInArbGas is the a hex encoded call to: - // `function getPricesInArbGas() external view returns (uint256, uint256, uint256);` - ArbGasInfo_getPricesInArbGas = "02199f34" -) - -// callGetPricesInArbGas calls ArbGasInfo.getPricesInArbGas() on the precompile contract ArbGasInfoAddress. -// -// @return (per L2 tx, per L1 calldata unit, per storage allocation) -// function getPricesInArbGas() external view returns (uint256, uint256, uint256); -// -// https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol#L69 -func (a *arbitrumEstimator) callGetPricesInArbGas() (perL2Tx uint32, perL1CalldataUnit uint32, err error) { - ctx, cancel := a.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) - defer cancel() - - precompile := common.HexToAddress(ArbGasInfoAddress) - b, err := a.client.CallContract(ctx, ethereum.CallMsg{ - To: &precompile, - Data: common.Hex2Bytes(ArbGasInfo_getPricesInArbGas), - }, big.NewInt(-1)) - if err != nil { - return 0, 0, err - } - - if len(b) != 3*32 { // returns (uint256, uint256, uint256); - err = fmt.Errorf("return data length (%d) different than expected (%d)", len(b), 3*32) - return - } - bPerL2Tx := new(big.Int).SetBytes(b[:32]) - bPerL1CalldataUnit := new(big.Int).SetBytes(b[32:64]) - // ignore perStorageAllocation - if !bPerL2Tx.IsUint64() || !bPerL1CalldataUnit.IsUint64() { - err = fmt.Errorf("returned integers are not uint64 (%s, %s)", bPerL2Tx.String(), bPerL1CalldataUnit.String()) - return - } - - perL2TxU64 := bPerL2Tx.Uint64() - perL1CalldataUnitU64 := bPerL1CalldataUnit.Uint64() - if perL2TxU64 > math.MaxUint32 || perL1CalldataUnitU64 > math.MaxUint32 { - err = fmt.Errorf("returned integers are not uint32 (%d, %d)", perL2TxU64, perL1CalldataUnitU64) - return - } - perL2Tx = uint32(perL2TxU64) - perL1CalldataUnit = uint32(perL1CalldataUnitU64) - return -} diff --git a/core/chains/evm/gas/arbitrum_estimator_test.go b/core/chains/evm/gas/arbitrum_estimator_test.go index 3c46b466e87..54d7fc333e3 100644 --- a/core/chains/evm/gas/arbitrum_estimator_test.go +++ b/core/chains/evm/gas/arbitrum_estimator_test.go @@ -19,6 +19,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -52,9 +53,10 @@ func TestArbitrumEstimator(t *testing.T) { var bumpMin = assets.NewWei(big.NewInt(1)) t.Run("calling GetLegacyGas on unstarted estimator returns error", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) _, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) assert.EqualError(t, err, "estimator is not started") }) @@ -64,21 +66,22 @@ func TestArbitrumEstimator(t *testing.T) { zeros.Write(common.BigToHash(big.NewInt(0)).Bytes()) zeros.Write(common.BigToHash(big.NewInt(123455)).Bytes()) t.Run("calling GetLegacyGas on started estimator returns estimates", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(zeros.Bytes(), nil) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient) + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) require.NoError(t, err) @@ -88,19 +91,20 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("gas price is lower than user specified max gas price", func(t *testing.T) { - client := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(zeros.Bytes(), nil) @@ -113,19 +117,20 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("gas price is lower than global max gas price", func(t *testing.T) { - ethClient := mocks.NewETHClient(t) - client := mocks.NewRPCClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(120) }) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(zeros.Bytes(), nil) @@ -137,24 +142,26 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on unstarted arbitrum estimator returns error", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) _, _, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), gasLimit, assets.NewWeiI(10), nil) assert.EqualError(t, err, "estimator is not started") }) t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, client, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(zeros.Bytes(), nil) @@ -165,17 +172,19 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("calling GetDynamicFee always returns error", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) _, err := o.GetDynamicFee(testutils.Context(t), maxGasPrice) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") }) t.Run("calling BumpDynamicFee always returns error", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, rpcClient, ethClient) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{}, feeEstimatorClient, l1Oracle) fee := gas.DynamicFee{ FeeCap: assets.NewWeiI(42), TipCap: assets.NewWeiI(5), @@ -185,9 +194,10 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("limit computes", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) @@ -201,15 +211,15 @@ func TestArbitrumEstimator(t *testing.T) { b.Write(common.BigToHash(big.NewInt(perL2Tx)).Bytes()) b.Write(common.BigToHash(big.NewInt(perL1Calldata)).Bytes()) b.Write(common.BigToHash(big.NewInt(123455)).Bytes()) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(b.Bytes(), nil) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient) + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) require.NoError(t, err) @@ -220,9 +230,10 @@ func TestArbitrumEstimator(t *testing.T) { }) t.Run("limit exceeds max", func(t *testing.T) { - rpcClient := mocks.NewRPCClient(t) - ethClient := mocks.NewETHClient(t) - rpcClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollups.NewArbitrumL1GasOracle(logger.Test(t), feeEstimatorClient) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) @@ -235,15 +246,15 @@ func TestArbitrumEstimator(t *testing.T) { b.Write(common.BigToHash(big.NewInt(perL2Tx)).Bytes()) b.Write(common.BigToHash(big.NewInt(perL1Calldata)).Bytes()) b.Write(common.BigToHash(big.NewInt(123455)).Bytes()) - ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) - assert.Equal(t, gas.ArbGasInfoAddress, callMsg.To.String()) - assert.Equal(t, gas.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) + assert.Equal(t, rollups.ArbGasInfoAddress, callMsg.To.String()) + assert.Equal(t, rollups.ArbGasInfo_getPricesInArbGas, fmt.Sprintf("%x", callMsg.Data)) assert.Equal(t, big.NewInt(-1), blockNumber) }).Return(b.Bytes(), nil) - o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, rpcClient, ethClient) + o := gas.NewArbitrumEstimator(logger.Test(t), &arbConfig{v: maxGasLimit, bumpPercent: bumpPercent, bumpMin: bumpMin}, feeEstimatorClient, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) require.Error(t, err, "expected error but got (%s, %d)", gasPrice, chainSpecificGasLimit) diff --git a/core/chains/evm/gas/block_history_estimator.go b/core/chains/evm/gas/block_history_estimator.go index 5fb9c5d7173..8b8c626f725 100644 --- a/core/chains/evm/gas/block_history_estimator.go +++ b/core/chains/evm/gas/block_history_estimator.go @@ -24,7 +24,7 @@ import ( commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -97,7 +97,7 @@ type estimatorGasEstimatorConfig interface { //go:generate mockery --quiet --name Config --output ./mocks/ --case=underscore type BlockHistoryEstimator struct { services.StateMachine - ethClient evmclient.Client + ethClient feeEstimatorClient chainID big.Int config chainConfig eConfig estimatorGasEstimatorConfig @@ -120,13 +120,16 @@ type BlockHistoryEstimator struct { initialFetch atomic.Bool logger logger.SugaredLogger + + l1Oracle rollups.L1Oracle } // NewBlockHistoryEstimator returns a new BlockHistoryEstimator that listens // for new heads and updates the base gas price dynamically based on the // configured percentile of gas prices in that block -func NewBlockHistoryEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg chainConfig, eCfg estimatorGasEstimatorConfig, bhCfg BlockHistoryConfig, chainID big.Int) EvmEstimator { +func NewBlockHistoryEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg chainConfig, eCfg estimatorGasEstimatorConfig, bhCfg BlockHistoryConfig, chainID big.Int, l1Oracle rollups.L1Oracle) EvmEstimator { ctx, cancel := context.WithCancel(context.Background()) + b := &BlockHistoryEstimator{ ethClient: ethClient, chainID: chainID, @@ -141,6 +144,7 @@ func NewBlockHistoryEstimator(lggr logger.Logger, ethClient evmclient.Client, cf ctx: ctx, ctxCancel: cancel, logger: logger.Sugared(logger.Named(lggr, "BlockHistoryEstimator")), + l1Oracle: l1Oracle, } return b @@ -230,6 +234,10 @@ func (b *BlockHistoryEstimator) Start(ctx context.Context) error { }) } +func (b *BlockHistoryEstimator) L1Oracle() rollups.L1Oracle { + return b.l1Oracle +} + func (b *BlockHistoryEstimator) Close() error { return b.StopOnce("BlockHistoryEstimator", func() error { b.ctxCancel() diff --git a/core/chains/evm/gas/block_history_estimator_test.go b/core/chains/evm/gas/block_history_estimator_test.go index 5260a22bff3..941b60545ba 100644 --- a/core/chains/evm/gas/block_history_estimator_test.go +++ b/core/chains/evm/gas/block_history_estimator_test.go @@ -24,6 +24,8 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" + rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" @@ -42,12 +44,12 @@ func newBlockHistoryConfig() *gas.MockBlockHistoryConfig { return c } -func newBlockHistoryEstimatorWithChainID(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig, cid big.Int) gas.EvmEstimator { - return gas.NewBlockHistoryEstimator(logger.Test(t), c, cfg, gCfg, bhCfg, cid) +func newBlockHistoryEstimatorWithChainID(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig, cid big.Int, l1Oracle rollups.L1Oracle) gas.EvmEstimator { + return gas.NewBlockHistoryEstimator(logger.Test(t), c, cfg, gCfg, bhCfg, cid, l1Oracle) } -func newBlockHistoryEstimator(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig) *gas.BlockHistoryEstimator { - iface := newBlockHistoryEstimatorWithChainID(t, c, cfg, gCfg, bhCfg, cltest.FixtureChainID) +func newBlockHistoryEstimator(t *testing.T, c evmclient.Client, cfg gas.Config, gCfg gas.GasEstimatorConfig, bhCfg gas.BlockHistoryConfig, l1Oracle rollups.L1Oracle) *gas.BlockHistoryEstimator { + iface := newBlockHistoryEstimatorWithChainID(t, c, cfg, gCfg, bhCfg, cltest.FixtureChainID, l1Oracle) return gas.BlockHistoryEstimatorFromInterface(iface) } @@ -77,8 +79,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("loads initial state", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -121,8 +124,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { cfg2 := gas.NewMockConfig() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg2, geCfg2, bhCfg2) + bhe := newBlockHistoryEstimator(t, ethClient, cfg2, geCfg2, bhCfg2, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -154,8 +158,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("boots even if initial batch call returns nothing", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -172,8 +177,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("starts anyway if fetching latest head fails", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(nil, pkgerrors.New("something exploded")) @@ -193,8 +199,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("starts anyway if fetching first fetch fails, but errors on estimation", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -216,8 +223,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("returns error if main context is cancelled", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -232,8 +240,9 @@ func TestBlockHistoryEstimator_Start(t *testing.T) { t.Run("starts anyway even if the fetch context is cancelled due to taking longer than the MaxStartTime", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(420)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -261,8 +270,9 @@ func TestBlockHistoryEstimator_OnNewLongestChain(t *testing.T) { bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) assert.Nil(t, gas.GetLatestBaseFee(bhe)) @@ -284,6 +294,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("with history size of 0, errors", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -295,7 +307,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) head := cltest.Head(42) err := bhe.FetchBlocks(testutils.Context(t), head) @@ -305,6 +317,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("with current block height less than block delay does nothing", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 = 3 @@ -315,7 +329,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) for i := -1; i < 3; i++ { head := cltest.Head(i) @@ -327,6 +341,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("with error retrieving blocks returns error", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 = 3 @@ -338,7 +354,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) ethClient.On("BatchCallContext", mock.Anything, mock.Anything).Return(pkgerrors.New("something exploded")) @@ -349,6 +365,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("batch fetches heads and transactions and sets them on the block history estimator instance", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 @@ -362,7 +380,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b41 := evmtypes.Block{ Number: 41, @@ -443,6 +461,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("does not refetch blocks below EVM.FinalityDepth", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 @@ -455,7 +475,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -506,6 +526,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("replaces blocks on re-org within EVM.FinalityDepth", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() var blockDelay uint16 @@ -518,7 +540,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -577,6 +599,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("uses locally cached blocks if they are in the chain", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() var blockDelay uint16 var historySize uint16 = 3 @@ -589,7 +613,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b0 := evmtypes.Block{ Number: 0, @@ -634,6 +658,8 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { t.Run("fetches max(BlockHistoryEstimatorCheckInclusionBlocks, BlockHistoryEstimatorBlockHistorySize)", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() var blockDelay uint16 var historySize uint16 = 1 @@ -648,7 +674,7 @@ func TestBlockHistoryEstimator_FetchBlocks(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b42 := evmtypes.Block{ Number: 42, @@ -686,6 +712,8 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) t.Parallel() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() bhCfg.BlockDelayF = uint16(0) @@ -698,7 +726,7 @@ func TestBlockHistoryEstimator_FetchBlocksAndRecalculate_NoEIP1559(t *testing.T) geCfg.PriceMaxF = assets.NewWeiI(1000) geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1 := evmtypes.Block{ Number: 1, @@ -744,6 +772,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("does not crash or set gas price to zero if there are no transactions", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -753,7 +782,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{} gas.SetRollingBlockHistory(bhe, blocks) @@ -770,6 +799,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("sets gas price to EVM.GasEstimator.PriceMax if the calculation would otherwise exceed it", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -780,7 +811,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -805,6 +836,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("sets gas price to EVM.GasEstimator.PriceMin if the calculation would otherwise fall below it", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -815,7 +848,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -840,6 +873,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("ignores any transaction with a zero gas limit", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -850,7 +885,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = minGasPrice - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() b2Hash := utils.NewHash() @@ -887,6 +922,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("takes into account zero priced transactions if chain is not Gnosis", func(t *testing.T) { // Because everyone loves free gas! ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -897,7 +934,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -920,6 +957,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("ignores zero priced transactions only on Gnosis", func(t *testing.T) { ethClient := evmtest.NewEthClientMock(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -930,7 +969,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(11) // Has to be set as Gnosis will only ignore transactions below this price - ibhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + ibhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) bhe := gas.BlockHistoryEstimatorFromInterface(ibhe) b1Hash := utils.NewHash() @@ -964,6 +1003,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { // Seems unlikely we will ever experience gas prices > 9 Petawei on mainnet (praying to the eth Gods 🙏) // But other chains could easily use a different base of account ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -976,7 +1017,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = reasonablyHugeGasPrice geCfg.PriceMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) unreasonablyHugeGasPrice := assets.NewWeiI(1000000).Mul(big.NewInt(math.MaxInt64)) @@ -1011,6 +1052,8 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { t.Run("doesn't panic if gas price is nil (although I'm still unsure how this can happen)", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1021,7 +1064,7 @@ func TestBlockHistoryEstimator_Recalculate_NoEIP1559(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(100) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1057,6 +1100,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("does not crash or set gas price to zero if there are no transactions", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1066,7 +1110,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{} gas.SetRollingBlockHistory(bhe, blocks) @@ -1095,6 +1139,8 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("does not set tip higher than EVM.GasEstimator.PriceMax", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1106,7 +1152,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1133,6 +1179,8 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("sets tip cap to EVM.GasEstimator.TipCapMin if the calculation would otherwise fall below it", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1144,7 +1192,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1171,6 +1219,8 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("ignores any transaction with a zero gas limit", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1182,7 +1232,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(10) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() b2Hash := utils.NewHash() @@ -1219,6 +1269,8 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("respects minimum gas tip cap", func(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1230,7 +1282,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(1) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1255,6 +1307,8 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { t.Run("allows to set zero tip cap if minimum allows it", func(t *testing.T) { // Because everyone loves *cheap* gas! ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1266,7 +1320,7 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { geCfg.PriceMinF = assets.NewWeiI(0) geCfg.TipCapMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) b1Hash := utils.NewHash() @@ -1291,12 +1345,14 @@ func TestBlockHistoryEstimator_Recalculate_EIP1559(t *testing.T) { func TestBlockHistoryEstimator_IsUsable(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, Hash: utils.NewHash(), @@ -1373,13 +1429,15 @@ func TestBlockHistoryEstimator_IsUsable(t *testing.T) { func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = true - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, @@ -1433,13 +1491,15 @@ func TestBlockHistoryEstimator_EffectiveTipCap(t *testing.T) { func TestBlockHistoryEstimator_EffectiveGasPrice(t *testing.T) { ethClient := evmtest.NewEthClientMockWithDefaultChain(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) block := evmtypes.Block{ Number: 0, @@ -1772,6 +1832,7 @@ func TestBlockHistoryEstimator_EIP1559Block_Unmarshal(t *testing.T) { func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { t.Parallel() + l1Oracle := rollupMocks.NewL1Oracle(t) cfg := gas.NewMockConfig() bhCfg := newBlockHistoryConfig() @@ -1786,7 +1847,7 @@ func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { geCfg.PriceMaxF = maxGasPrice geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -1830,7 +1891,7 @@ func TestBlockHistoryEstimator_GetLegacyGas(t *testing.T) { geCfg.EIP1559DynamicFeesF = false - bhe = newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe = newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) gas.SetRollingBlockHistory(bhe, blocks) bhe.Recalculate(cltest.Head(1)) gas.SimulateStart(t, bhe) @@ -1867,7 +1928,9 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { geCfg.PriceDefaultF = assets.NewWeiI(100) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + l1Oracle := rollupMocks.NewL1Oracle(t) + + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: nil} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -1918,7 +1981,9 @@ func TestBlockHistoryEstimator_UseDefaultPriceAsFallback(t *testing.T) { geCfg.BumpThresholdF = uint64(1) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg) + l1Oracle := rollupMocks.NewL1Oracle(t) + + bhe := newBlockHistoryEstimator(t, ethClient, cfg, geCfg, bhCfg, l1Oracle) h := &evmtypes.Head{Hash: utils.NewHash(), Number: 42, BaseFeePerGas: assets.NewWeiI(40)} ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(h, nil) @@ -1967,7 +2032,9 @@ func TestBlockHistoryEstimator_GetDynamicFee(t *testing.T) { geCfg.TipCapMinF = assets.NewWeiI(0) geCfg.PriceMinF = assets.NewWeiI(0) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + l1Oracle := rollupMocks.NewL1Oracle(t) + + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) blocks := []evmtypes.Block{ { @@ -2065,9 +2132,10 @@ func TestBlockHistoryEstimator_CheckConnectivity(t *testing.T) { lggr, obs := logger.TestObserved(t, zapcore.DebugLevel) geCfg := &gas.MockGasEstimatorConfig{} geCfg.EIP1559DynamicFeesF = false + l1Oracle := rollupMocks.NewL1Oracle(t) bhe := gas.BlockHistoryEstimatorFromInterface( - gas.NewBlockHistoryEstimator(lggr, nil, cfg, geCfg, bhCfg, *testutils.NewRandomEVMChainID()), + gas.NewBlockHistoryEstimator(lggr, nil, cfg, geCfg, bhCfg, *testutils.NewRandomEVMChainID(), l1Oracle), ) attempts := []gas.EvmPriorAttempt{ @@ -2365,8 +2433,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) b1 := evmtypes.Block{ Number: 1, @@ -2394,8 +2463,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) t.Run("ignores nil current gas price", func(t *testing.T) { gasPrice, gasLimit, err := bhe.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), 100000, maxGasPrice, nil) @@ -2475,8 +2545,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpPercentF = 10 geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) b1 := evmtypes.Block{ BaseFeePerGas: assets.NewWeiI(1), @@ -2508,8 +2579,9 @@ func TestBlockHistoryEstimator_Bumps(t *testing.T) { geCfg.BumpMinF = assets.NewWeiI(150) geCfg.PriceMaxF = maxGasPrice geCfg.TipCapDefaultF = assets.NewWeiI(52) + l1Oracle := rollupMocks.NewL1Oracle(t) - bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg) + bhe := newBlockHistoryEstimator(t, nil, cfg, geCfg, bhCfg, l1Oracle) t.Run("when current tip cap is nil", func(t *testing.T) { originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} diff --git a/core/chains/evm/gas/cmd/arbgas/main.go b/core/chains/evm/gas/cmd/arbgas/main.go deleted file mode 100644 index dc107a50b52..00000000000 --- a/core/chains/evm/gas/cmd/arbgas/main.go +++ /dev/null @@ -1,85 +0,0 @@ -// arbgas takes a single URL argument and prints the result of three GetLegacyGas calls to the Arbitrum gas estimator. -package main - -import ( - "context" - "fmt" - "log" - "os" - - "github.com/ethereum/go-ethereum/ethclient" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" -) - -func main() { - if l := len(os.Args); l != 2 { - log.Fatal("Expected one URL argument but got", l-1) - } - url := os.Args[1] - lggr, err := logger.New() - if err != nil { - log.Fatal("Failed to create logger:", err) - } - - ctx := context.Background() - withEstimator(ctx, logger.Sugared(lggr), url, func(e gas.EvmEstimator) { - printGetLegacyGas(ctx, e, make([]byte, 10), 500_000, assets.GWei(1)) - printGetLegacyGas(ctx, e, make([]byte, 10), 500_000, assets.GWei(1), feetypes.OptForceRefetch) - printGetLegacyGas(ctx, e, make([]byte, 10), max, assets.GWei(1)) - }) -} - -func printGetLegacyGas(ctx context.Context, e gas.EvmEstimator, calldata []byte, l2GasLimit uint64, maxGasPrice *assets.Wei, opts ...feetypes.Opt) { - price, limit, err := e.GetLegacyGas(ctx, calldata, l2GasLimit, maxGasPrice, opts...) - if err != nil { - log.Println("failed to get legacy gas:", err) - return - } - fmt.Println("Price:", price) - fmt.Println("Limit:", limit) -} - -const max = 50_000_000 - -func withEstimator(ctx context.Context, lggr logger.SugaredLogger, url string, f func(e gas.EvmEstimator)) { - rc, err := rpc.Dial(url) - if err != nil { - log.Fatal(err) - } - ec := ethclient.NewClient(rc) - e := gas.NewArbitrumEstimator(lggr, &config{max: max}, rc, ec) - ctx, cancel := context.WithCancel(ctx) - defer cancel() - err = e.Start(ctx) - if err != nil { - log.Fatal(err) - } - defer lggr.ErrorIfFn(e.Close, "Error closing ArbitrumEstimator") - - f(e) -} - -var _ gas.ArbConfig = &config{} - -type config struct { - max uint64 - bumpPercent uint16 - bumpMin *assets.Wei -} - -func (c *config) LimitMax() uint64 { - return c.max -} - -func (c *config) BumpPercent() uint16 { - return c.bumpPercent -} - -func (c *config) BumpMin() *assets.Wei { - return c.bumpMin -} diff --git a/core/chains/evm/gas/fixed_price_estimator.go b/core/chains/evm/gas/fixed_price_estimator.go index fc65413d375..f4749b093a1 100644 --- a/core/chains/evm/gas/fixed_price_estimator.go +++ b/core/chains/evm/gas/fixed_price_estimator.go @@ -9,6 +9,7 @@ import ( commonfee "github.com/smartcontractkit/chainlink/v2/common/fee" feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -18,6 +19,7 @@ type fixedPriceEstimator struct { config fixedPriceEstimatorConfig bhConfig fixedPriceEstimatorBlockHistoryConfig lggr logger.SugaredLogger + l1Oracle rollups.L1Oracle } type bumpConfig interface { LimitMultiplier() float32 @@ -43,8 +45,8 @@ type fixedPriceEstimatorBlockHistoryConfig interface { // NewFixedPriceEstimator returns a new "FixedPrice" estimator which will // always use the config default values for gas prices and limits -func NewFixedPriceEstimator(cfg fixedPriceEstimatorConfig, bhCfg fixedPriceEstimatorBlockHistoryConfig, lggr logger.Logger) EvmEstimator { - return &fixedPriceEstimator{cfg, bhCfg, logger.Sugared(logger.Named(lggr, "FixedPriceEstimator"))} +func NewFixedPriceEstimator(cfg fixedPriceEstimatorConfig, ethClient feeEstimatorClient, bhCfg fixedPriceEstimatorBlockHistoryConfig, lggr logger.Logger, l1Oracle rollups.L1Oracle) EvmEstimator { + return &fixedPriceEstimator{cfg, bhCfg, logger.Sugared(logger.Named(lggr, "FixedPriceEstimator")), l1Oracle} } func (f *fixedPriceEstimator) Start(context.Context) error { @@ -128,6 +130,10 @@ func (f *fixedPriceEstimator) BumpDynamicFee( ) } +func (f *fixedPriceEstimator) L1Oracle() rollups.L1Oracle { + return f.l1Oracle +} + func (f *fixedPriceEstimator) Name() string { return f.lggr.Name() } func (f *fixedPriceEstimator) Ready() error { return nil } func (f *fixedPriceEstimator) HealthReport() map[string]error { return map[string]error{} } diff --git a/core/chains/evm/gas/fixed_price_estimator_test.go b/core/chains/evm/gas/fixed_price_estimator_test.go index c31bd41aeee..9c68f9d2fbc 100644 --- a/core/chains/evm/gas/fixed_price_estimator_test.go +++ b/core/chains/evm/gas/fixed_price_estimator_test.go @@ -9,6 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" + rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -26,7 +27,9 @@ func Test_FixedPriceEstimator(t *testing.T) { t.Run("GetLegacyGas returns EvmGasPriceDefault from config", func(t *testing.T) { config := &gas.MockGasEstimatorConfig{} - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, logger.Test(t)) + l1Oracle := rollupMocks.NewL1Oracle(t) + + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, logger.Test(t), l1Oracle) config.PriceDefaultF = assets.NewWeiI(42) config.PriceMaxF = maxGasPrice @@ -41,7 +44,9 @@ func Test_FixedPriceEstimator(t *testing.T) { config := &gas.MockGasEstimatorConfig{} config.PriceDefaultF = assets.NewWeiI(42) config.PriceMaxF = assets.NewWeiI(35) - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, logger.Test(t)) + l1Oracle := rollupMocks.NewL1Oracle(t) + + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, logger.Test(t), l1Oracle) gasPrice, gasLimit, err := f.GetLegacyGas(testutils.Context(t), nil, 100000, assets.NewWeiI(30)) require.NoError(t, err) @@ -53,8 +58,9 @@ func Test_FixedPriceEstimator(t *testing.T) { config := &gas.MockGasEstimatorConfig{} config.PriceDefaultF = assets.NewWeiI(42) config.PriceMaxF = assets.NewWeiI(20) + l1Oracle := rollupMocks.NewL1Oracle(t) - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, logger.Test(t)) + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, logger.Test(t), l1Oracle) gasPrice, gasLimit, err := f.GetLegacyGas(testutils.Context(t), nil, 100000, assets.NewWeiI(30)) require.NoError(t, err) assert.Equal(t, 100000, int(gasLimit)) @@ -67,9 +73,10 @@ func Test_FixedPriceEstimator(t *testing.T) { config.PriceMaxF = maxGasPrice config.BumpPercentF = uint16(10) config.BumpMinF = assets.NewWeiI(150) + l1Oracle := rollupMocks.NewL1Oracle(t) lggr := logger.TestSugared(t) - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, lggr) + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, lggr, l1Oracle) gasPrice, gasLimit, err := f.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), 100000, maxGasPrice, nil) require.NoError(t, err) @@ -87,9 +94,10 @@ func Test_FixedPriceEstimator(t *testing.T) { config.TipCapDefaultF = assets.NewWeiI(52) config.FeeCapDefaultF = assets.NewWeiI(100) config.BumpThresholdF = uint64(3) + l1Oracle := rollupMocks.NewL1Oracle(t) lggr := logger.Test(t) - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, lggr) + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, lggr, l1Oracle) fee, err := f.GetDynamicFee(testutils.Context(t), maxGasPrice) require.NoError(t, err) @@ -120,9 +128,10 @@ func Test_FixedPriceEstimator(t *testing.T) { config.TipCapDefaultF = assets.NewWeiI(52) config.BumpMinF = assets.NewWeiI(150) config.BumpPercentF = uint16(10) + l1Oracle := rollupMocks.NewL1Oracle(t) lggr := logger.TestSugared(t) - f := gas.NewFixedPriceEstimator(config, &blockHistoryConfig{}, lggr) + f := gas.NewFixedPriceEstimator(config, nil, &blockHistoryConfig{}, lggr, l1Oracle) originalFee := gas.DynamicFee{FeeCap: assets.NewWeiI(100), TipCap: assets.NewWeiI(25)} fee, err := f.BumpDynamicFee(testutils.Context(t), originalFee, maxGasPrice, nil) diff --git a/core/chains/evm/gas/mocks/eth_client.go b/core/chains/evm/gas/mocks/eth_client.go deleted file mode 100644 index bb0784f8515..00000000000 --- a/core/chains/evm/gas/mocks/eth_client.go +++ /dev/null @@ -1,61 +0,0 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - ethereum "github.com/ethereum/go-ethereum" - - mock "github.com/stretchr/testify/mock" -) - -// ETHClient is an autogenerated mock type for the ethClient type -type ETHClient struct { - mock.Mock -} - -// CallContract provides a mock function with given fields: ctx, msg, blockNumber -func (_m *ETHClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { - ret := _m.Called(ctx, msg, blockNumber) - - if len(ret) == 0 { - panic("no return value specified for CallContract") - } - - var r0 []byte - var r1 error - if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok { - return rf(ctx, msg, blockNumber) - } - if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) []byte); ok { - r0 = rf(ctx, msg, blockNumber) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).([]byte) - } - } - - if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg, *big.Int) error); ok { - r1 = rf(ctx, msg, blockNumber) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewETHClient creates a new instance of ETHClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewETHClient(t interface { - mock.TestingT - Cleanup(func()) -}) *ETHClient { - mock := ÐClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/gas/mocks/evm_estimator.go b/core/chains/evm/gas/mocks/evm_estimator.go index a0b6fa62432..600e43a7c69 100644 --- a/core/chains/evm/gas/mocks/evm_estimator.go +++ b/core/chains/evm/gas/mocks/evm_estimator.go @@ -13,6 +13,8 @@ import ( mock "github.com/stretchr/testify/mock" + rollups "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" + types "github.com/smartcontractkit/chainlink/v2/common/fee/types" ) @@ -196,6 +198,26 @@ func (_m *EvmEstimator) HealthReport() map[string]error { return r0 } +// L1Oracle provides a mock function with given fields: +func (_m *EvmEstimator) L1Oracle() rollups.L1Oracle { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for L1Oracle") + } + + var r0 rollups.L1Oracle + if rf, ok := ret.Get(0).(func() rollups.L1Oracle); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(rollups.L1Oracle) + } + } + + return r0 +} + // Name provides a mock function with given fields: func (_m *EvmEstimator) Name() string { ret := _m.Called() diff --git a/core/chains/evm/gas/mocks/fee_estimator_client.go b/core/chains/evm/gas/mocks/fee_estimator_client.go new file mode 100644 index 00000000000..50eb17d2dac --- /dev/null +++ b/core/chains/evm/gas/mocks/fee_estimator_client.go @@ -0,0 +1,154 @@ +// Code generated by mockery v2.38.0. DO NOT EDIT. + +package mocks + +import ( + context "context" + big "math/big" + + ethereum "github.com/ethereum/go-ethereum" + + mock "github.com/stretchr/testify/mock" + + rpc "github.com/ethereum/go-ethereum/rpc" + + types "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" +) + +// FeeEstimatorClient is an autogenerated mock type for the feeEstimatorClient type +type FeeEstimatorClient struct { + mock.Mock +} + +// BatchCallContext provides a mock function with given fields: ctx, b +func (_m *FeeEstimatorClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { + ret := _m.Called(ctx, b) + + if len(ret) == 0 { + panic("no return value specified for BatchCallContext") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, []rpc.BatchElem) error); ok { + r0 = rf(ctx, b) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CallContext provides a mock function with given fields: ctx, result, method, args +func (_m *FeeEstimatorClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { + var _ca []interface{} + _ca = append(_ca, ctx, result, method) + _ca = append(_ca, args...) + ret := _m.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for CallContext") + } + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, interface{}, string, ...interface{}) error); ok { + r0 = rf(ctx, result, method, args...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// CallContract provides a mock function with given fields: ctx, msg, blockNumber +func (_m *FeeEstimatorClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { + ret := _m.Called(ctx, msg, blockNumber) + + if len(ret) == 0 { + panic("no return value specified for CallContract") + } + + var r0 []byte + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) ([]byte, error)); ok { + return rf(ctx, msg, blockNumber) + } + if rf, ok := ret.Get(0).(func(context.Context, ethereum.CallMsg, *big.Int) []byte); ok { + r0 = rf(ctx, msg, blockNumber) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).([]byte) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, ethereum.CallMsg, *big.Int) error); ok { + r1 = rf(ctx, msg, blockNumber) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ConfiguredChainID provides a mock function with given fields: +func (_m *FeeEstimatorClient) ConfiguredChainID() *big.Int { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for ConfiguredChainID") + } + + var r0 *big.Int + if rf, ok := ret.Get(0).(func() *big.Int); ok { + r0 = rf() + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*big.Int) + } + } + + return r0 +} + +// HeadByNumber provides a mock function with given fields: ctx, n +func (_m *FeeEstimatorClient) HeadByNumber(ctx context.Context, n *big.Int) (*types.Head, error) { + ret := _m.Called(ctx, n) + + if len(ret) == 0 { + panic("no return value specified for HeadByNumber") + } + + var r0 *types.Head + var r1 error + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) (*types.Head, error)); ok { + return rf(ctx, n) + } + if rf, ok := ret.Get(0).(func(context.Context, *big.Int) *types.Head); ok { + r0 = rf(ctx, n) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*types.Head) + } + } + + if rf, ok := ret.Get(1).(func(context.Context, *big.Int) error); ok { + r1 = rf(ctx, n) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewFeeEstimatorClient creates a new instance of FeeEstimatorClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewFeeEstimatorClient(t interface { + mock.TestingT + Cleanup(func()) +}) *FeeEstimatorClient { + mock := &FeeEstimatorClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/chains/evm/gas/mocks/rpc_client.go b/core/chains/evm/gas/mocks/rpc_client.go deleted file mode 100644 index d1262665f66..00000000000 --- a/core/chains/evm/gas/mocks/rpc_client.go +++ /dev/null @@ -1,49 +0,0 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - - mock "github.com/stretchr/testify/mock" -) - -// RPCClient is an autogenerated mock type for the rpcClient type -type RPCClient struct { - mock.Mock -} - -// CallContext provides a mock function with given fields: ctx, result, method, args -func (_m *RPCClient) CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error { - var _ca []interface{} - _ca = append(_ca, ctx, result, method) - _ca = append(_ca, args...) - ret := _m.Called(_ca...) - - if len(ret) == 0 { - panic("no return value specified for CallContext") - } - - var r0 error - if rf, ok := ret.Get(0).(func(context.Context, interface{}, string, ...interface{}) error); ok { - r0 = rf(ctx, result, method, args...) - } else { - r0 = ret.Error(0) - } - - return r0 -} - -// NewRPCClient creates a new instance of RPCClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewRPCClient(t interface { - mock.TestingT - Cleanup(func()) -}) *RPCClient { - mock := &RPCClient{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/gas/models.go b/core/chains/evm/gas/models.go index 04673d5a622..c50e19373f1 100644 --- a/core/chains/evm/gas/models.go +++ b/core/chains/evm/gas/models.go @@ -5,8 +5,10 @@ import ( "fmt" "math/big" + "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" pkgerrors "github.com/pkg/errors" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -18,7 +20,6 @@ import ( feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/common/headtracker" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/label" @@ -41,8 +42,17 @@ type EvmFeeEstimator interface { GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) } +//go:generate mockery --quiet --name feeEstimatorClient --output ./mocks/ --case=underscore --structname FeeEstimatorClient +type feeEstimatorClient interface { + CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error + ConfiguredChainID() *big.Int + HeadByNumber(ctx context.Context, n *big.Int) (*evmtypes.Head, error) +} + // NewEstimator returns the estimator for a given config -func NewEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg Config, geCfg evmconfig.GasEstimator) EvmFeeEstimator { +func NewEstimator(lggr logger.Logger, ethClient feeEstimatorClient, cfg Config, geCfg evmconfig.GasEstimator) EvmFeeEstimator { bh := geCfg.BlockHistory() s := geCfg.Mode() lggr.Infow(fmt.Sprintf("Initializing EVM gas estimator in mode: %s", s), @@ -75,27 +85,27 @@ func NewEstimator(lggr logger.Logger, ethClient evmclient.Client, cfg Config, ge switch s { case "Arbitrum": newEstimator = func(l logger.Logger) EvmEstimator { - return NewArbitrumEstimator(lggr, geCfg, ethClient, ethClient) + return NewArbitrumEstimator(lggr, geCfg, ethClient, rollups.NewArbitrumL1GasOracle(lggr, ethClient)) } case "BlockHistory": newEstimator = func(l logger.Logger) EvmEstimator { - return NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, *ethClient.ConfiguredChainID()) + return NewBlockHistoryEstimator(lggr, ethClient, cfg, geCfg, bh, *ethClient.ConfiguredChainID(), l1Oracle) } case "FixedPrice": newEstimator = func(l logger.Logger) EvmEstimator { - return NewFixedPriceEstimator(geCfg, bh, lggr) + return NewFixedPriceEstimator(geCfg, ethClient, bh, lggr, l1Oracle) } case "L2Suggested", "SuggestedPrice": newEstimator = func(l logger.Logger) EvmEstimator { - return NewSuggestedPriceEstimator(lggr, ethClient, geCfg) + return NewSuggestedPriceEstimator(lggr, ethClient, geCfg, l1Oracle) } default: lggr.Warnf("GasEstimator: unrecognised mode '%s', falling back to FixedPriceEstimator", s) newEstimator = func(l logger.Logger) EvmEstimator { - return NewFixedPriceEstimator(geCfg, bh, lggr) + return NewFixedPriceEstimator(geCfg, ethClient, bh, lggr, l1Oracle) } } - return NewWrappedEvmEstimator(lggr, newEstimator, df, l1Oracle, geCfg) + return NewEvmFeeEstimator(lggr, newEstimator, df, geCfg) } // DynamicFee encompasses both FeeCap and TipCap for EIP1559 transactions @@ -138,6 +148,8 @@ type EvmEstimator interface { // - be sorted in order from highest price to lowest price // - all be of transaction type 0x2 BumpDynamicFee(ctx context.Context, original DynamicFee, maxGasPriceWei *assets.Wei, attempts []EvmPriorAttempt) (bumped DynamicFee, err error) + + L1Oracle() rollups.L1Oracle } var _ feetypes.Fee = (*EvmFee)(nil) @@ -159,53 +171,53 @@ func (fee EvmFee) ValidDynamic() bool { return fee.DynamicFeeCap != nil && fee.DynamicTipCap != nil } -// WrappedEvmEstimator provides a struct that wraps the EVM specific dynamic and legacy estimators into one estimator that conforms to the generic FeeEstimator -type WrappedEvmEstimator struct { +// evmFeeEstimator provides a struct that wraps the EVM specific dynamic and legacy estimators into one estimator that conforms to the generic FeeEstimator +type evmFeeEstimator struct { services.StateMachine lggr logger.Logger EvmEstimator EIP1559Enabled bool - l1Oracle rollups.L1Oracle geCfg GasEstimatorConfig } -var _ EvmFeeEstimator = (*WrappedEvmEstimator)(nil) +var _ EvmFeeEstimator = (*evmFeeEstimator)(nil) -func NewWrappedEvmEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, l1Oracle rollups.L1Oracle, geCfg GasEstimatorConfig) EvmFeeEstimator { +func NewEvmFeeEstimator(lggr logger.Logger, newEstimator func(logger.Logger) EvmEstimator, eip1559Enabled bool, geCfg GasEstimatorConfig) EvmFeeEstimator { lggr = logger.Named(lggr, "WrappedEvmEstimator") - return &WrappedEvmEstimator{ + return &evmFeeEstimator{ lggr: lggr, EvmEstimator: newEstimator(lggr), EIP1559Enabled: eip1559Enabled, - l1Oracle: l1Oracle, geCfg: geCfg, } } -func (e *WrappedEvmEstimator) Name() string { +func (e *evmFeeEstimator) Name() string { return e.lggr.Name() } -func (e *WrappedEvmEstimator) Start(ctx context.Context) error { +func (e *evmFeeEstimator) Start(ctx context.Context) error { return e.StartOnce(e.Name(), func() error { if err := e.EvmEstimator.Start(ctx); err != nil { return pkgerrors.Wrap(err, "failed to start EVMEstimator") } - if e.l1Oracle != nil { - if err := e.l1Oracle.Start(ctx); err != nil { + l1Oracle := e.L1Oracle() + if l1Oracle != nil { + if err := l1Oracle.Start(ctx); err != nil { return pkgerrors.Wrap(err, "failed to start L1Oracle") } } return nil }) } -func (e *WrappedEvmEstimator) Close() error { +func (e *evmFeeEstimator) Close() error { return e.StopOnce(e.Name(), func() error { var errEVM, errOracle error errEVM = pkgerrors.Wrap(e.EvmEstimator.Close(), "failed to stop EVMEstimator") - if e.l1Oracle != nil { - errOracle = pkgerrors.Wrap(e.l1Oracle.Close(), "failed to stop L1Oracle") + l1Oracle := e.L1Oracle() + if l1Oracle != nil { + errOracle = pkgerrors.Wrap(l1Oracle.Close(), "failed to stop L1Oracle") } if errEVM != nil { @@ -215,12 +227,13 @@ func (e *WrappedEvmEstimator) Close() error { }) } -func (e *WrappedEvmEstimator) Ready() error { +func (e *evmFeeEstimator) Ready() error { var errEVM, errOracle error errEVM = e.EvmEstimator.Ready() - if e.l1Oracle != nil { - errOracle = e.l1Oracle.Ready() + l1Oracle := e.L1Oracle() + if l1Oracle != nil { + errOracle = l1Oracle.Ready() } if errEVM != nil { @@ -229,21 +242,23 @@ func (e *WrappedEvmEstimator) Ready() error { return errOracle } -func (e *WrappedEvmEstimator) HealthReport() map[string]error { +func (e *evmFeeEstimator) HealthReport() map[string]error { report := map[string]error{e.Name(): e.Healthy()} services.CopyHealth(report, e.EvmEstimator.HealthReport()) - if e.l1Oracle != nil { - services.CopyHealth(report, e.l1Oracle.HealthReport()) + + l1Oracle := e.L1Oracle() + if l1Oracle != nil { + services.CopyHealth(report, l1Oracle.HealthReport()) } return report } -func (e *WrappedEvmEstimator) L1Oracle() rollups.L1Oracle { - return e.l1Oracle +func (e *evmFeeEstimator) L1Oracle() rollups.L1Oracle { + return e.EvmEstimator.L1Oracle() } -func (e *WrappedEvmEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) { +func (e *evmFeeEstimator) GetFee(ctx context.Context, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (fee EvmFee, chainSpecificFeeLimit uint64, err error) { // get dynamic fee if e.EIP1559Enabled { var dynamicFee DynamicFee @@ -267,7 +282,7 @@ func (e *WrappedEvmEstimator) GetFee(ctx context.Context, calldata []byte, feeLi return } -func (e *WrappedEvmEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) { +func (e *evmFeeEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, calldata []byte, feeLimit uint64, maxFeePrice *assets.Wei, opts ...feetypes.Opt) (*big.Int, error) { fees, gasLimit, err := e.GetFee(ctx, calldata, feeLimit, maxFeePrice, opts...) if err != nil { return nil, err @@ -285,7 +300,7 @@ func (e *WrappedEvmEstimator) GetMaxCost(ctx context.Context, amount assets.Eth, return amountWithFees, nil } -func (e *WrappedEvmEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) { +func (e *evmFeeEstimator) BumpFee(ctx context.Context, originalFee EvmFee, feeLimit uint64, maxFeePrice *assets.Wei, attempts []EvmPriorAttempt) (bumpedFee EvmFee, chainSpecificFeeLimit uint64, err error) { // validate only 1 fee type is present if (!originalFee.ValidDynamic() && originalFee.Legacy == nil) || (originalFee.ValidDynamic() && originalFee.Legacy != nil) { err = pkgerrors.New("only one dynamic or legacy fee can be defined") diff --git a/core/chains/evm/gas/models_test.go b/core/chains/evm/gas/models_test.go index ec9542b4040..722beb8021a 100644 --- a/core/chains/evm/gas/models_test.go +++ b/core/chains/evm/gas/models_test.go @@ -10,9 +10,11 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -49,14 +51,24 @@ func TestWrappedEvmEstimator(t *testing.T) { // L1Oracle returns the correct L1Oracle interface t.Run("L1Oracle", func(t *testing.T) { lggr := logger.Test(t) + + evmEstimator := mocks.NewEvmEstimator(t) + evmEstimator.On("L1Oracle").Return(nil).Once() + + getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } + // expect nil - estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, false, nil, nil) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, nil) l1Oracle := estimator.L1Oracle() + assert.Nil(t, l1Oracle) // expect l1Oracle - oracle := rollupMocks.NewL1Oracle(t) - estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, false, oracle, geCfg) + oracle := rollups.NewL1GasOracle(lggr, nil, config.ChainOptimismBedrock) + // cast oracle to L1Oracle interface + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) + + evmEstimator.On("L1Oracle").Return(oracle).Once() l1Oracle = estimator.L1Oracle() assert.Equal(t, oracle, l1Oracle) }) @@ -66,7 +78,7 @@ func TestWrappedEvmEstimator(t *testing.T) { lggr := logger.Test(t) // expect legacy fee data dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) fee, max, err := estimator.GetFee(ctx, nil, 0, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) @@ -76,7 +88,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) fee, max, err = estimator.GetFee(ctx, nil, gasLimit, nil) require.NoError(t, err) assert.Equal(t, uint64(float32(gasLimit)*limitMultiplier), max) @@ -89,7 +101,7 @@ func TestWrappedEvmEstimator(t *testing.T) { t.Run("BumpFee", func(t *testing.T) { lggr := logger.Test(t) dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) // expect legacy fee data fee, max, err := estimator.BumpFee(ctx, gas.EvmFee{Legacy: assets.NewWeiI(0)}, 0, nil, nil) @@ -127,7 +139,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect legacy fee data dynamicFees := false - estimator := gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) total, err := estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) require.NoError(t, err) fee := new(big.Int).Mul(legacyFee.ToInt(), big.NewInt(int64(gasLimit))) @@ -136,7 +148,7 @@ func TestWrappedEvmEstimator(t *testing.T) { // expect dynamic fee data dynamicFees = true - estimator = gas.NewWrappedEvmEstimator(lggr, getRootEst, dynamicFees, nil, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getRootEst, dynamicFees, geCfg) total, err = estimator.GetMaxCost(ctx, val, nil, gasLimit, nil) require.NoError(t, err) fee = new(big.Int).Mul(dynamicFee.FeeCap.ToInt(), big.NewInt(int64(gasLimit))) @@ -147,13 +159,12 @@ func TestWrappedEvmEstimator(t *testing.T) { t.Run("Name", func(t *testing.T) { lggr := logger.Test(t) - oracle := rollupMocks.NewL1Oracle(t) evmEstimator := mocks.NewEvmEstimator(t) evmEstimator.On("Name").Return(mockEvmEstimatorName, nil).Once() - estimator := gas.NewWrappedEvmEstimator(lggr, func(logger.Logger) gas.EvmEstimator { + estimator := gas.NewEvmFeeEstimator(lggr, func(logger.Logger) gas.EvmEstimator { return evmEstimator - }, false, oracle, geCfg) + }, false, geCfg) require.Equal(t, mockEstimatorName, estimator.Name()) require.Equal(t, mockEvmEstimatorName, evmEstimator.Name()) @@ -170,13 +181,17 @@ func TestWrappedEvmEstimator(t *testing.T) { oracle.On("Close").Return(nil).Once() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg) + evmEstimator.On("L1Oracle", mock.Anything).Return(nil).Twice() + + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) err := estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() require.NoError(t, err) - estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg) + evmEstimator.On("L1Oracle", mock.Anything).Return(oracle).Twice() + + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) err = estimator.Start(ctx) require.NoError(t, err) err = estimator.Close() @@ -188,15 +203,16 @@ func TestWrappedEvmEstimator(t *testing.T) { evmEstimator := mocks.NewEvmEstimator(t) oracle := rollupMocks.NewL1Oracle(t) + evmEstimator.On("L1Oracle").Return(oracle).Twice() evmEstimator.On("Ready").Return(nil).Twice() - oracle.On("Ready").Return(nil).Once() + oracle.On("Ready").Return(nil).Twice() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) err := estimator.Ready() require.NoError(t, err) - estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg) + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) err = estimator.Ready() require.NoError(t, err) }) @@ -211,17 +227,21 @@ func TestWrappedEvmEstimator(t *testing.T) { oracleKey := "oracle" oracleError := pkgerrors.New("oracle error") + evmEstimator.On("L1Oracle").Return(nil).Once() evmEstimator.On("HealthReport").Return(map[string]error{evmEstimatorKey: evmEstimatorError}).Twice() + oracle.On("HealthReport").Return(map[string]error{oracleKey: oracleError}).Once() getEst := func(logger.Logger) gas.EvmEstimator { return evmEstimator } - estimator := gas.NewWrappedEvmEstimator(lggr, getEst, false, nil, geCfg) + estimator := gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) report := estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.Nil(t, report[oracleKey]) require.NotNil(t, report[mockEstimatorName]) - estimator = gas.NewWrappedEvmEstimator(lggr, getEst, false, oracle, geCfg) + evmEstimator.On("L1Oracle").Return(oracle).Once() + + estimator = gas.NewEvmFeeEstimator(lggr, getEst, false, geCfg) report = estimator.HealthReport() require.True(t, pkgerrors.Is(report[evmEstimatorKey], evmEstimatorError)) require.True(t, pkgerrors.Is(report[oracleKey], oracleError)) diff --git a/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go new file mode 100644 index 00000000000..d0b4c5808ad --- /dev/null +++ b/core/chains/evm/gas/rollups/arbitrum_l1_oracle.go @@ -0,0 +1,300 @@ +package rollups + +import ( + "context" + "fmt" + "math" + "math/big" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + gethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" +) + +type ArbL1GasOracle interface { + L1Oracle + GetPricesInArbGas() (perL2Tx uint32, perL1CalldataUnit uint32, err error) +} + +// Reads L2-specific precompiles and caches the l1GasPrice set by the L2. +type arbitrumL1Oracle struct { + services.StateMachine + client l1OracleClient + pollPeriod time.Duration + logger logger.SugaredLogger + chainType config.ChainType + + l1GasPriceAddress string + gasPriceMethod string + l1GasPriceMethodAbi abi.ABI + l1GasPriceMu sync.RWMutex + l1GasPrice priceEntry + + l1GasCostAddress string + gasCostMethod string + l1GasCostMethodAbi abi.ABI + + chInitialised chan struct{} + chStop services.StopChan + chDone chan struct{} +} + +const ( + // ArbGasInfoAddress is the address of the "Precompiled contract that exists in every Arbitrum chain." + // https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol + ArbGasInfoAddress = "0x000000000000000000000000000000000000006C" + // ArbGasInfo_getL1BaseFeeEstimate is the a hex encoded call to: + // `function getL1BaseFeeEstimate() external view returns (uint256);` + ArbGasInfo_getL1BaseFeeEstimate = "getL1BaseFeeEstimate" + // NodeInterfaceAddress is the address of the precompiled contract that is only available through RPC + // https://github.com/OffchainLabs/nitro/blob/e815395d2e91fb17f4634cad72198f6de79c6e61/nodeInterface/NodeInterface.go#L37 + ArbNodeInterfaceAddress = "0x00000000000000000000000000000000000000C8" + // ArbGasInfo_getPricesInArbGas is the a hex encoded call to: + // `function gasEstimateL1Component(address to, bool contractCreation, bytes calldata data) external payable returns (uint64 gasEstimateForL1, uint256 baseFee, uint256 l1BaseFeeEstimate);` + ArbNodeInterface_gasEstimateL1Component = "gasEstimateL1Component" + // ArbGasInfo_getPricesInArbGas is the a hex encoded call to: + // `function getPricesInArbGas() external view returns (uint256, uint256, uint256);` + ArbGasInfo_getPricesInArbGas = "02199f34" +) + +func NewArbitrumL1GasOracle(lggr logger.Logger, ethClient l1OracleClient) *arbitrumL1Oracle { + var l1GasPriceAddress, gasPriceMethod, l1GasCostAddress, gasCostMethod string + var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI + var gasPriceErr, gasCostErr error + + l1GasPriceAddress = ArbGasInfoAddress + gasPriceMethod = ArbGasInfo_getL1BaseFeeEstimate + l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(GetL1BaseFeeEstimateAbiString)) + l1GasCostAddress = ArbNodeInterfaceAddress + gasCostMethod = ArbNodeInterface_gasEstimateL1Component + l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GasEstimateL1ComponentAbiString)) + + if gasPriceErr != nil { + panic("Failed to parse L1 gas price method ABI for chain: arbitrum") + } + if gasCostErr != nil { + panic("Failed to parse L1 gas cost method ABI for chain: arbitrum") + } + + return &arbitrumL1Oracle{ + client: ethClient, + pollPeriod: PollPeriod, + logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(arbitrum)")), + chainType: config.ChainArbitrum, + + l1GasPriceAddress: l1GasPriceAddress, + gasPriceMethod: gasPriceMethod, + l1GasPriceMethodAbi: l1GasPriceMethodAbi, + l1GasCostAddress: l1GasCostAddress, + gasCostMethod: gasCostMethod, + l1GasCostMethodAbi: l1GasCostMethodAbi, + + chInitialised: make(chan struct{}), + chStop: make(chan struct{}), + chDone: make(chan struct{}), + } +} + +func (o *arbitrumL1Oracle) Name() string { + return o.logger.Name() +} + +func (o *arbitrumL1Oracle) Start(ctx context.Context) error { + return o.StartOnce(o.Name(), func() error { + go o.run() + <-o.chInitialised + return nil + }) +} +func (o *arbitrumL1Oracle) Close() error { + return o.StopOnce(o.Name(), func() error { + close(o.chStop) + <-o.chDone + return nil + }) +} + +func (o *arbitrumL1Oracle) HealthReport() map[string]error { + return map[string]error{o.Name(): o.Healthy()} +} + +func (o *arbitrumL1Oracle) run() { + defer close(o.chDone) + + t := o.refresh() + close(o.chInitialised) + + for { + select { + case <-o.chStop: + return + case <-t.C: + t = o.refresh() + } + } +} +func (o *arbitrumL1Oracle) refresh() (t *time.Timer) { + t, err := o.refreshWithError() + if err != nil { + o.SvcErrBuffer.Append(err) + } + return +} + +func (o *arbitrumL1Oracle) refreshWithError() (t *time.Timer, err error) { + t = time.NewTimer(utils.WithJitter(o.pollPeriod)) + + ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + price, err := o.fetchL1GasPrice(ctx) + if err != nil { + return t, err + } + + o.l1GasPriceMu.Lock() + defer o.l1GasPriceMu.Unlock() + o.l1GasPrice = priceEntry{price: assets.NewWei(price), timestamp: time.Now()} + return +} + +func (o *arbitrumL1Oracle) fetchL1GasPrice(ctx context.Context) (price *big.Int, err error) { + var callData, b []byte + precompile := common.HexToAddress(o.l1GasPriceAddress) + callData, err = o.l1GasPriceMethodAbi.Pack(o.gasPriceMethod) + if err != nil { + errMsg := "failed to pack calldata for arbitrum L1 gas price method" + o.logger.Errorf(errMsg) + return nil, fmt.Errorf("%s: %w", errMsg, err) + } + b, err = o.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: callData, + }, nil) + if err != nil { + errMsg := "gas oracle contract call failed" + o.logger.Errorf(errMsg) + return nil, fmt.Errorf("%s: %w", errMsg, err) + } + + if len(b) != 32 { // returns uint256; + errMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) + o.logger.Criticalf(errMsg) + return nil, fmt.Errorf(errMsg) + } + price = new(big.Int).SetBytes(b) + return price, nil +} + +func (o *arbitrumL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { + var timestamp time.Time + ok := o.IfStarted(func() { + o.l1GasPriceMu.RLock() + l1GasPrice = o.l1GasPrice.price + timestamp = o.l1GasPrice.timestamp + o.l1GasPriceMu.RUnlock() + }) + if !ok { + return l1GasPrice, fmt.Errorf("L1GasOracle is not started; cannot estimate gas") + } + if l1GasPrice == nil { + return l1GasPrice, fmt.Errorf("failed to get l1 gas price; gas price not set") + } + // Validate the price has been updated within the pollPeriod * 2 + // Allowing double the poll period before declaring the price stale to give ample time for the refresh to process + if time.Since(timestamp) > o.pollPeriod*2 { + return l1GasPrice, fmt.Errorf("gas price is stale") + } + return +} + +// Gets the L1 gas cost for the provided transaction at the specified block num +// If block num is not provided, the value on the latest block num is used +func (o *arbitrumL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { + ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) + defer cancel() + var callData, b []byte + var err error + + if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, tx.To(), false, tx.Data()); err != nil { + return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) + } + + precompile := common.HexToAddress(o.l1GasCostAddress) + b, err = o.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: callData, + }, blockNum) + if err != nil { + errorMsg := fmt.Sprintf("gas oracle contract call failed: %v", err) + o.logger.Errorf(errorMsg) + return nil, fmt.Errorf(errorMsg) + } + + var l1GasCost *big.Int + + if len(b) != 8+2*32 { // returns (uint64 gasEstimateForL1, uint256 baseFee, uint256 l1BaseFeeEstimate); + errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 8+2*32) + o.logger.Critical(errorMsg) + return nil, fmt.Errorf(errorMsg) + } + l1GasCost = new(big.Int).SetBytes(b[:8]) + + return assets.NewWei(l1GasCost), nil +} + +// callGetPricesInArbGas calls ArbGasInfo.getPricesInArbGas() on the precompile contract ArbGasInfoAddress. +// +// @return (per L2 tx, per L1 calldata unit, per storage allocation) +// function getPricesInArbGas() external view returns (uint256, uint256, uint256); +// +// https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol#L69 + +func (o *arbitrumL1Oracle) GetPricesInArbGas() (perL2Tx uint32, perL1CalldataUnit uint32, err error) { + ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + precompile := common.HexToAddress(ArbGasInfoAddress) + b, err := o.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: common.Hex2Bytes(ArbGasInfo_getPricesInArbGas), + }, big.NewInt(-1)) + if err != nil { + return 0, 0, err + } + + if len(b) != 3*32 { // returns (uint256, uint256, uint256); + err = fmt.Errorf("return data length (%d) different than expected (%d)", len(b), 3*32) + return + } + bPerL2Tx := new(big.Int).SetBytes(b[:32]) + bPerL1CalldataUnit := new(big.Int).SetBytes(b[32:64]) + // ignore perStorageAllocation + if !bPerL2Tx.IsUint64() || !bPerL1CalldataUnit.IsUint64() { + err = fmt.Errorf("returned integers are not uint64 (%s, %s)", bPerL2Tx.String(), bPerL1CalldataUnit.String()) + return + } + + perL2TxU64 := bPerL2Tx.Uint64() + perL1CalldataUnitU64 := bPerL1CalldataUnit.Uint64() + if perL2TxU64 > math.MaxUint32 || perL1CalldataUnitU64 > math.MaxUint32 { + err = fmt.Errorf("returned integers are not uint32 (%d, %d)", perL2TxU64, perL1CalldataUnitU64) + return + } + perL2Tx = uint32(perL2TxU64) + perL1CalldataUnit = uint32(perL1CalldataUnitU64) + return +} diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index ae46071cf0d..05ceb720ab2 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -5,36 +5,35 @@ import ( "fmt" "math/big" "slices" - "strings" - "sync" "time" "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rpc" - "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink-common/pkg/utils" - gethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/smartcontractkit/chainlink-common/pkg/logger" - "github.com/smartcontractkit/chainlink/v2/common/client" "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" - evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" ) -//go:generate mockery --quiet --name ethClient --output ./mocks/ --case=underscore --structname ETHClient -type ethClient interface { - CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) - BatchCallContext(ctx context.Context, b []rpc.BatchElem) error +// L1Oracle provides interface for fetching L1-specific fee components if the chain is an L2. +// For example, on Optimistic Rollups, this oracle can return rollup-specific l1BaseFee +// +//go:generate mockery --quiet --name L1Oracle --output ./mocks/ --case=underscore +type L1Oracle interface { + services.Service + + GasPrice(ctx context.Context) (*assets.Wei, error) + GetGasCost(ctx context.Context, tx *types.Transaction, blockNum *big.Int) (*assets.Wei, error) } -//go:generate mockery --quiet --name daPriceReader --output ./mocks/ --case=underscore --structname DAPriceReader -type daPriceReader interface { - GetDAGasPrice(ctx context.Context) (*big.Int, error) +//go:generate mockery --quiet --name l1OracleClient --output ./mocks/ --case=underscore --structname L1OracleClient +type l1OracleClient interface { + CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) + BatchCallContext(ctx context.Context, b []rpc.BatchElem) error } type priceEntry struct { @@ -42,71 +41,7 @@ type priceEntry struct { timestamp time.Time } -// Reads L2-specific precompiles and caches the l1GasPrice set by the L2. -type l1Oracle struct { - services.StateMachine - client ethClient - pollPeriod time.Duration - logger logger.SugaredLogger - chainType config.ChainType - - l1GasPriceAddress string - gasPriceMethod string - l1GasPriceMethodAbi abi.ABI - l1GasPriceMu sync.RWMutex - l1GasPrice priceEntry - - l1GasCostAddress string - gasCostMethod string - l1GasCostMethodAbi abi.ABI - - priceReader daPriceReader - - chInitialised chan struct{} - chStop services.StopChan - chDone chan struct{} -} - const ( - // ArbGasInfoAddress is the address of the "Precompiled contract that exists in every Arbitrum chain." - // https://github.com/OffchainLabs/nitro/blob/f7645453cfc77bf3e3644ea1ac031eff629df325/contracts/src/precompiles/ArbGasInfo.sol - ArbGasInfoAddress = "0x000000000000000000000000000000000000006C" - // ArbGasInfo_getL1BaseFeeEstimate is the a hex encoded call to: - // `function getL1BaseFeeEstimate() external view returns (uint256);` - ArbGasInfo_getL1BaseFeeEstimate = "getL1BaseFeeEstimate" - // NodeInterfaceAddress is the address of the precompiled contract that is only available through RPC - // https://github.com/OffchainLabs/nitro/blob/e815395d2e91fb17f4634cad72198f6de79c6e61/nodeInterface/NodeInterface.go#L37 - ArbNodeInterfaceAddress = "0x00000000000000000000000000000000000000C8" - // ArbGasInfo_getPricesInArbGas is the a hex encoded call to: - // `function gasEstimateL1Component(address to, bool contractCreation, bytes calldata data) external payable returns (uint64 gasEstimateForL1, uint256 baseFee, uint256 l1BaseFeeEstimate);` - ArbNodeInterface_gasEstimateL1Component = "gasEstimateL1Component" - - // OPGasOracleAddress is the address of the precompiled contract that exists on OP stack chain. - // This is the case for Optimism and Base. - OPGasOracleAddress = "0x420000000000000000000000000000000000000F" - // OPGasOracle_l1BaseFee is a hex encoded call to: - // `function l1BaseFee() external view returns (uint256);` - OPGasOracle_l1BaseFee = "l1BaseFee" - // OPGasOracle_getL1Fee is a hex encoded call to: - // `function getL1Fee(bytes) external view returns (uint256);` - OPGasOracle_getL1Fee = "getL1Fee" - - // ScrollGasOracleAddress is the address of the precompiled contract that exists on Scroll chain. - ScrollGasOracleAddress = "0x5300000000000000000000000000000000000002" - // ScrollGasOracle_l1BaseFee is a hex encoded call to: - // `function l1BaseFee() external view returns (uint256);` - ScrollGasOracle_l1BaseFee = "l1BaseFee" - // ScrollGasOracle_getL1Fee is a hex encoded call to: - // `function getL1Fee(bytes) external view returns (uint256);` - ScrollGasOracle_getL1Fee = "getL1Fee" - - // GasOracleAddress is the address of the precompiled contract that exists on Kroma chain. - // This is the case for Kroma. - KromaGasOracleAddress = "0x4200000000000000000000000000000000000005" - // GasOracle_l1BaseFee is the a hex encoded call to: - // `function l1BaseFee() external view returns (uint256);` - KromaGasOracle_l1BaseFee = "l1BaseFee" - // Interval at which to poll for L1BaseFee. A good starting point is the L1 block time. PollPeriod = 6 * time.Second ) @@ -117,253 +52,18 @@ func IsRollupWithL1Support(chainType config.ChainType) bool { return slices.Contains(supportedChainTypes, chainType) } -func NewL1GasOracle(lggr logger.Logger, ethClient ethClient, chainType config.ChainType) L1Oracle { - var priceReader daPriceReader - switch chainType { - case config.ChainOptimismBedrock: - priceReader = newOPPriceReader(lggr, ethClient, chainType, OPGasOracleAddress) - case config.ChainKroma: - priceReader = newOPPriceReader(lggr, ethClient, chainType, KromaGasOracleAddress) - default: - priceReader = nil +func NewL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType) L1Oracle { + if !IsRollupWithL1Support(chainType) { + return nil } - return newL1GasOracle(lggr, ethClient, chainType, priceReader) -} - -func newL1GasOracle(lggr logger.Logger, ethClient ethClient, chainType config.ChainType, priceReader daPriceReader) L1Oracle { - var l1GasPriceAddress, gasPriceMethod, l1GasCostAddress, gasCostMethod string - var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI - var gasPriceErr, gasCostErr error - + var l1Oracle L1Oracle switch chainType { + case config.ChainOptimismBedrock, config.ChainKroma, config.ChainScroll: + l1Oracle = NewOpStackL1GasOracle(lggr, ethClient, chainType) case config.ChainArbitrum: - l1GasPriceAddress = ArbGasInfoAddress - gasPriceMethod = ArbGasInfo_getL1BaseFeeEstimate - l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(GetL1BaseFeeEstimateAbiString)) - l1GasCostAddress = ArbNodeInterfaceAddress - gasCostMethod = ArbNodeInterface_gasEstimateL1Component - l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GasEstimateL1ComponentAbiString)) - case config.ChainOptimismBedrock: - l1GasPriceAddress = OPGasOracleAddress - gasPriceMethod = OPGasOracle_l1BaseFee - l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - l1GasCostAddress = OPGasOracleAddress - gasCostMethod = OPGasOracle_getL1Fee - l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GetL1FeeAbiString)) - case config.ChainKroma: - l1GasPriceAddress = KromaGasOracleAddress - gasPriceMethod = KromaGasOracle_l1BaseFee - l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - l1GasCostAddress = "" - gasCostMethod = "" - case config.ChainScroll: - l1GasPriceAddress = ScrollGasOracleAddress - gasPriceMethod = ScrollGasOracle_l1BaseFee - l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - l1GasCostAddress = ScrollGasOracleAddress - gasCostMethod = ScrollGasOracle_getL1Fee - l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GetL1FeeAbiString)) + l1Oracle = NewArbitrumL1GasOracle(lggr, ethClient) default: panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) } - - if gasPriceErr != nil { - panic(fmt.Sprintf("Failed to parse L1 gas price method ABI for chain: %s", chainType)) - } - if gasCostErr != nil { - panic(fmt.Sprintf("Failed to parse L1 gas cost method ABI for chain: %s", chainType)) - } - - return &l1Oracle{ - client: ethClient, - pollPeriod: PollPeriod, - logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("L1GasOracle(%s)", chainType))), - chainType: chainType, - - l1GasPriceAddress: l1GasPriceAddress, - gasPriceMethod: gasPriceMethod, - l1GasPriceMethodAbi: l1GasPriceMethodAbi, - l1GasCostAddress: l1GasCostAddress, - gasCostMethod: gasCostMethod, - l1GasCostMethodAbi: l1GasCostMethodAbi, - - priceReader: priceReader, - - chInitialised: make(chan struct{}), - chStop: make(chan struct{}), - chDone: make(chan struct{}), - } -} - -func (o *l1Oracle) Name() string { - return o.logger.Name() -} - -func (o *l1Oracle) Start(ctx context.Context) error { - return o.StartOnce(o.Name(), func() error { - go o.run() - <-o.chInitialised - return nil - }) -} -func (o *l1Oracle) Close() error { - return o.StopOnce(o.Name(), func() error { - close(o.chStop) - <-o.chDone - return nil - }) -} - -func (o *l1Oracle) HealthReport() map[string]error { - return map[string]error{o.Name(): o.Healthy()} -} - -func (o *l1Oracle) run() { - defer close(o.chDone) - - t := o.refresh() - close(o.chInitialised) - - for { - select { - case <-o.chStop: - return - case <-t.C: - t = o.refresh() - } - } -} -func (o *l1Oracle) refresh() (t *time.Timer) { - t, err := o.refreshWithError() - if err != nil { - o.SvcErrBuffer.Append(err) - } - return -} - -func (o *l1Oracle) refreshWithError() (t *time.Timer, err error) { - t = time.NewTimer(utils.WithJitter(o.pollPeriod)) - - ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) - defer cancel() - - price, err := o.fetchL1GasPrice(ctx) - if err != nil { - return t, err - } - - o.l1GasPriceMu.Lock() - defer o.l1GasPriceMu.Unlock() - o.l1GasPrice = priceEntry{price: assets.NewWei(price), timestamp: time.Now()} - return -} - -func (o *l1Oracle) fetchL1GasPrice(ctx context.Context) (price *big.Int, err error) { - // if dedicated priceReader exists, use the reader - if o.priceReader != nil { - return o.priceReader.GetDAGasPrice(ctx) - } - - var callData, b []byte - precompile := common.HexToAddress(o.l1GasPriceAddress) - callData, err = o.l1GasPriceMethodAbi.Pack(o.gasPriceMethod) - if err != nil { - errMsg := fmt.Sprintf("failed to pack calldata for %s L1 gas price method", o.chainType) - o.logger.Errorf(errMsg) - return nil, fmt.Errorf("%s: %w", errMsg, err) - } - b, err = o.client.CallContract(ctx, ethereum.CallMsg{ - To: &precompile, - Data: callData, - }, nil) - if err != nil { - errMsg := "gas oracle contract call failed" - o.logger.Errorf(errMsg) - return nil, fmt.Errorf("%s: %w", errMsg, err) - } - - if len(b) != 32 { // returns uint256; - errMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) - o.logger.Criticalf(errMsg) - return nil, fmt.Errorf(errMsg) - } - price = new(big.Int).SetBytes(b) - return price, nil -} - -func (o *l1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { - var timestamp time.Time - ok := o.IfStarted(func() { - o.l1GasPriceMu.RLock() - l1GasPrice = o.l1GasPrice.price - timestamp = o.l1GasPrice.timestamp - o.l1GasPriceMu.RUnlock() - }) - if !ok { - return l1GasPrice, fmt.Errorf("L1GasOracle is not started; cannot estimate gas") - } - if l1GasPrice == nil { - return l1GasPrice, fmt.Errorf("failed to get l1 gas price; gas price not set") - } - // Validate the price has been updated within the pollPeriod * 2 - // Allowing double the poll period before declaring the price stale to give ample time for the refresh to process - if time.Since(timestamp) > o.pollPeriod*2 { - return l1GasPrice, fmt.Errorf("gas price is stale") - } - return -} - -// Gets the L1 gas cost for the provided transaction at the specified block num -// If block num is not provided, the value on the latest block num is used -func (o *l1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { - ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) - defer cancel() - var callData, b []byte - var err error - if o.chainType == config.ChainOptimismBedrock || o.chainType == config.ChainScroll { - // Append rlp-encoded tx - var encodedtx []byte - if encodedtx, err = tx.MarshalBinary(); err != nil { - return nil, fmt.Errorf("failed to marshal tx for gas cost estimation: %w", err) - } - if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, encodedtx); err != nil { - return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) - } - } else if o.chainType == config.ChainArbitrum { - if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, tx.To(), false, tx.Data()); err != nil { - return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) - } - } else { - return nil, fmt.Errorf("L1 gas cost not supported for this chain: %s", o.chainType) - } - - precompile := common.HexToAddress(o.l1GasCostAddress) - b, err = o.client.CallContract(ctx, ethereum.CallMsg{ - To: &precompile, - Data: callData, - }, blockNum) - if err != nil { - errorMsg := fmt.Sprintf("gas oracle contract call failed: %v", err) - o.logger.Errorf(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - - var l1GasCost *big.Int - if o.chainType == config.ChainOptimismBedrock || o.chainType == config.ChainScroll { - if len(b) != 32 { // returns uint256; - errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) - o.logger.Critical(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - l1GasCost = new(big.Int).SetBytes(b) - } else if o.chainType == config.ChainArbitrum { - if len(b) != 8+2*32 { // returns (uint64 gasEstimateForL1, uint256 baseFee, uint256 l1BaseFeeEstimate); - errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 8+2*32) - o.logger.Critical(errorMsg) - return nil, fmt.Errorf(errorMsg) - } - l1GasCost = new(big.Int).SetBytes(b[:8]) - } - - return assets.NewWei(l1GasCost), nil + return l1Oracle } diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index 4f3b67e2ecf..6efdda6bcff 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -1,6 +1,7 @@ package rollups import ( + "errors" "math/big" "strings" "testing" @@ -27,9 +28,9 @@ func TestL1Oracle(t *testing.T) { t.Parallel() t.Run("Unsupported ChainType returns nil", func(t *testing.T) { - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) - assert.Panicsf(t, func() { NewL1GasOracle(logger.Test(t), ethClient, config.ChainCelo) }, "Received unspported chaintype %s", config.ChainCelo) + assert.Nil(t, NewL1GasOracle(logger.Test(t), ethClient, config.ChainCelo)) }) } @@ -37,7 +38,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Parallel() t.Run("Calling GasPrice on unstarted L1Oracle returns error", func(t *testing.T) { - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock) @@ -50,7 +51,7 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(GetL1BaseFeeEstimateAbiString)) require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -73,10 +74,34 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Run("Calling GasPrice on started Kroma L1Oracle returns Kroma l1GasPrice", func(t *testing.T) { l1BaseFee := big.NewInt(100) - priceReader := mocks.NewDAPriceReader(t) - priceReader.On("GetDAGasPrice", mock.Anything).Return(l1BaseFee, nil) + l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + require.NoError(t, err) + + isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) + require.NoError(t, err) + + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + var payload []byte + payload, err = isEcotoneAbiString.Pack("isEcotone") + require.NoError(t, err) + require.Equal(t, payload, callMsg.Data) + assert.Nil(t, blockNumber) + }).Return(nil, errors.New("not ecotone")).Once() - oracle := newL1GasOracle(logger.Test(t), nil, config.ChainKroma, priceReader) + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + var payload []byte + payload, err = l1GasPriceMethodAbi.Pack("l1BaseFee") + require.NoError(t, err) + require.Equal(t, payload, callMsg.Data) + assert.Nil(t, blockNumber) + }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) + + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainKroma, KromaGasOracleAddress) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(testutils.Context(t)) @@ -88,10 +113,34 @@ func TestL1Oracle_GasPrice(t *testing.T) { t.Run("Calling GasPrice on started OPStack L1Oracle returns OPStack l1GasPrice", func(t *testing.T) { l1BaseFee := big.NewInt(100) - priceReader := mocks.NewDAPriceReader(t) - priceReader.On("GetDAGasPrice", mock.Anything).Return(l1BaseFee, nil) + l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + require.NoError(t, err) + + isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) + require.NoError(t, err) + + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + var payload []byte + payload, err = isEcotoneAbiString.Pack("isEcotone") + require.NoError(t, err) + require.Equal(t, payload, callMsg.Data) + assert.Nil(t, blockNumber) + }).Return(nil, errors.New("not ecotone")).Once() - oracle := newL1GasOracle(logger.Test(t), nil, config.ChainOptimismBedrock, priceReader) + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + var payload []byte + payload, err = l1GasPriceMethodAbi.Pack("l1BaseFee") + require.NoError(t, err) + require.Equal(t, payload, callMsg.Data) + assert.Nil(t, blockNumber) + }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) + + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, OPGasOracleAddress) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(testutils.Context(t)) @@ -105,7 +154,20 @@ func TestL1Oracle_GasPrice(t *testing.T) { l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + isEcotoneAbiString, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) + require.NoError(t, err) + + ethClient := mocks.NewL1OracleClient(t) + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { + callMsg := args.Get(1).(ethereum.CallMsg) + blockNumber := args.Get(2).(*big.Int) + var payload []byte + payload, err = isEcotoneAbiString.Pack("isEcotone") + require.NoError(t, err) + require.Equal(t, payload, callMsg.Data) + assert.Nil(t, blockNumber) + }).Return(nil, errors.New("not ecotone")).Once() + ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -149,7 +211,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { result = append(result, baseFee...) result = append(result, l1BaseFeeEstimate...) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -171,7 +233,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { blockNum := big.NewInt(1000) tx := types.NewTx(&types.LegacyTx{}) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainKroma) _, err := oracle.GetGasCost(testutils.Context(t), tx, blockNum) @@ -195,7 +257,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { encodedTx, err := tx.MarshalBinary() require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -230,7 +292,7 @@ func TestL1Oracle_GetGasCost(t *testing.T) { encodedTx, err := tx.MarshalBinary() require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) diff --git a/core/chains/evm/gas/rollups/mocks/da_price_reader.go b/core/chains/evm/gas/rollups/mocks/da_price_reader.go deleted file mode 100644 index 7758f53e436..00000000000 --- a/core/chains/evm/gas/rollups/mocks/da_price_reader.go +++ /dev/null @@ -1,59 +0,0 @@ -// Code generated by mockery v2.38.0. DO NOT EDIT. - -package mocks - -import ( - context "context" - big "math/big" - - mock "github.com/stretchr/testify/mock" -) - -// DAPriceReader is an autogenerated mock type for the daPriceReader type -type DAPriceReader struct { - mock.Mock -} - -// GetDAGasPrice provides a mock function with given fields: ctx -func (_m *DAPriceReader) GetDAGasPrice(ctx context.Context) (*big.Int, error) { - ret := _m.Called(ctx) - - if len(ret) == 0 { - panic("no return value specified for GetDAGasPrice") - } - - var r0 *big.Int - var r1 error - if rf, ok := ret.Get(0).(func(context.Context) (*big.Int, error)); ok { - return rf(ctx) - } - if rf, ok := ret.Get(0).(func(context.Context) *big.Int); ok { - r0 = rf(ctx) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(*big.Int) - } - } - - if rf, ok := ret.Get(1).(func(context.Context) error); ok { - r1 = rf(ctx) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// NewDAPriceReader creates a new instance of DAPriceReader. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewDAPriceReader(t interface { - mock.TestingT - Cleanup(func()) -}) *DAPriceReader { - mock := &DAPriceReader{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/chains/evm/gas/rollups/mocks/eth_client.go b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go similarity index 72% rename from core/chains/evm/gas/rollups/mocks/eth_client.go rename to core/chains/evm/gas/rollups/mocks/l1_oracle_client.go index e5a28f715ad..3995a09513b 100644 --- a/core/chains/evm/gas/rollups/mocks/eth_client.go +++ b/core/chains/evm/gas/rollups/mocks/l1_oracle_client.go @@ -13,13 +13,13 @@ import ( rpc "github.com/ethereum/go-ethereum/rpc" ) -// ETHClient is an autogenerated mock type for the ethClient type -type ETHClient struct { +// L1OracleClient is an autogenerated mock type for the l1OracleClient type +type L1OracleClient struct { mock.Mock } // BatchCallContext provides a mock function with given fields: ctx, b -func (_m *ETHClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { +func (_m *L1OracleClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) error { ret := _m.Called(ctx, b) if len(ret) == 0 { @@ -37,7 +37,7 @@ func (_m *ETHClient) BatchCallContext(ctx context.Context, b []rpc.BatchElem) er } // CallContract provides a mock function with given fields: ctx, msg, blockNumber -func (_m *ETHClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { +func (_m *L1OracleClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blockNumber *big.Int) ([]byte, error) { ret := _m.Called(ctx, msg, blockNumber) if len(ret) == 0 { @@ -66,13 +66,13 @@ func (_m *ETHClient) CallContract(ctx context.Context, msg ethereum.CallMsg, blo return r0, r1 } -// NewETHClient creates a new instance of ETHClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// NewL1OracleClient creates a new instance of L1OracleClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. // The first argument is typically a *testing.T value. -func NewETHClient(t interface { +func NewL1OracleClient(t interface { mock.TestingT Cleanup(func()) -}) *ETHClient { - mock := ÐClient{} +}) *L1OracleClient { + mock := &L1OracleClient{} mock.Mock.Test(t) t.Cleanup(func() { mock.AssertExpectations(t) }) diff --git a/core/chains/evm/gas/rollups/models.go b/core/chains/evm/gas/rollups/models.go deleted file mode 100644 index 7aa3d4059dd..00000000000 --- a/core/chains/evm/gas/rollups/models.go +++ /dev/null @@ -1,22 +0,0 @@ -package rollups - -import ( - "context" - "math/big" - - "github.com/ethereum/go-ethereum/core/types" - - "github.com/smartcontractkit/chainlink-common/pkg/services" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" -) - -// L1Oracle provides interface for fetching L1-specific fee components if the chain is an L2. -// For example, on Optimistic Rollups, this oracle can return rollup-specific l1BaseFee -// -//go:generate mockery --quiet --name L1Oracle --output ./mocks/ --case=underscore -type L1Oracle interface { - services.Service - - GasPrice(ctx context.Context) (*assets.Wei, error) - GetGasCost(ctx context.Context, tx *types.Transaction, blockNum *big.Int) (*assets.Wei, error) -} diff --git a/core/chains/evm/gas/rollups/op_l1_oracle.go b/core/chains/evm/gas/rollups/op_l1_oracle.go new file mode 100644 index 00000000000..e180777fb61 --- /dev/null +++ b/core/chains/evm/gas/rollups/op_l1_oracle.go @@ -0,0 +1,431 @@ +package rollups + +import ( + "context" + "fmt" + "math/big" + "strings" + "sync" + "time" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/rpc" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/services" + "github.com/smartcontractkit/chainlink-common/pkg/utils" + + gethtypes "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink/v2/common/client" + "github.com/smartcontractkit/chainlink/v2/common/config" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" +) + +// Reads L2-specific precompiles and caches the l1GasPrice set by the L2. +type OptimismL1Oracle struct { + services.StateMachine + client l1OracleClient + pollPeriod time.Duration + logger logger.SugaredLogger + chainType config.ChainType + + l1OracleAddress string + gasPriceMethod string + l1GasPriceMethodAbi abi.ABI + l1GasPriceMu sync.RWMutex + l1GasPrice priceEntry + + gasCostMethod string + l1GasCostMethodAbi abi.ABI + + chInitialised chan struct{} + chStop services.StopChan + chDone chan struct{} + + isEcotoneMethodAbi abi.ABI + + l1BaseFeeCalldata []byte + isEcotoneCalldata []byte + getL1GasUsedCalldata []byte + getL1FeeCalldata []byte + + isEcotone bool + isEcotoneCheckTs int64 +} + +const ( + // OPStackGasOracle_isEcotone fetches if the OP Stack GasPriceOracle contract has upgraded to Ecotone + OPStackGasOracle_isEcotone = "isEcotone" + // OPStackGasOracle_getL1GasUsed fetches the l1 gas used for given tx bytes + OPStackGasOracle_getL1GasUsed = "getL1GasUsed" + // OPStackGasOracle_isEcotonePollingPeriod is the interval to poll if chain has upgraded to Ecotone + // Set to poll every 4 hours + OPStackGasOracle_isEcotonePollingPeriod = 14400 + // OPStackGasOracleAddress is the address of the precompiled contract that exists on OP stack chain. + // OPStackGasOracle_l1BaseFee fetches the l1 base fee set in the OP Stack GasPriceOracle contract + // OPStackGasOracle_l1BaseFee is a hex encoded call to: + // `function l1BaseFee() external view returns (uint256);` + OPStackGasOracle_l1BaseFee = "l1BaseFee" + // OPStackGasOracle_getL1Fee fetches the l1 fee for given tx bytes + // OPStackGasOracle_getL1Fee is a hex encoded call to: + // `function getL1Fee(bytes) external view returns (uint256);` + OPStackGasOracle_getL1Fee = "getL1Fee" + // This is the case for Optimism and Base. + OPGasOracleAddress = "0x420000000000000000000000000000000000000F" + // GasOracleAddress is the address of the precompiled contract that exists on Kroma chain. + // This is the case for Kroma. + KromaGasOracleAddress = "0x4200000000000000000000000000000000000005" + // ScrollGasOracleAddress is the address of the precompiled contract that exists on Scroll chain. + ScrollGasOracleAddress = "0x5300000000000000000000000000000000000002" +) + +func NewOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType) *OptimismL1Oracle { + var precompileAddress string + switch chainType { + case config.ChainOptimismBedrock: + precompileAddress = OPGasOracleAddress + case config.ChainKroma: + precompileAddress = KromaGasOracleAddress + case config.ChainScroll: + precompileAddress = ScrollGasOracleAddress + default: + panic(fmt.Sprintf("Received unspported chaintype %s", chainType)) + } + return newOpStackL1GasOracle(lggr, ethClient, chainType, precompileAddress) +} + +func newOpStackL1GasOracle(lggr logger.Logger, ethClient l1OracleClient, chainType config.ChainType, precompileAddress string) *OptimismL1Oracle { + var l1OracleAddress, gasPriceMethod, gasCostMethod string + var l1GasPriceMethodAbi, l1GasCostMethodAbi abi.ABI + var gasPriceErr, gasCostErr error + + l1OracleAddress = precompileAddress + gasPriceMethod = OPStackGasOracle_l1BaseFee + l1GasPriceMethodAbi, gasPriceErr = abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + gasCostMethod = OPStackGasOracle_getL1Fee + l1GasCostMethodAbi, gasCostErr = abi.JSON(strings.NewReader(GetL1FeeAbiString)) + + if gasPriceErr != nil { + panic(fmt.Sprintf("Failed to parse L1 gas price method ABI for chain: %s", chainType)) + } + if gasCostErr != nil { + panic(fmt.Sprintf("Failed to parse L1 gas cost method ABI for chain: %s", chainType)) + } + + // encode calldata for each method; these calldata will remain the same for each call, we can encode them just once + l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) + } + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(OPStackGasOracle_l1BaseFee) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) + } + + isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) + } + isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) + } + + getL1GasUsedMethodAbi, err := abi.JSON(strings.NewReader(OPGetL1GasUsedAbiString)) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) + } + getL1GasUsedCalldata, err := getL1GasUsedMethodAbi.Pack(OPStackGasOracle_getL1GasUsed, []byte{0x1}) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) + } + + getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) + } + getL1FeeCalldata, err := getL1FeeMethodAbi.Pack(OPStackGasOracle_getL1Fee, []byte{0x1}) + if err != nil { + panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) + } + + return &OptimismL1Oracle{ + client: ethClient, + pollPeriod: PollPeriod, + logger: logger.Sugared(logger.Named(lggr, "L1GasOracle(optimismBedrock)")), + chainType: chainType, + + l1OracleAddress: l1OracleAddress, + gasPriceMethod: gasPriceMethod, + l1GasPriceMethodAbi: l1GasPriceMethodAbi, + gasCostMethod: gasCostMethod, + l1GasCostMethodAbi: l1GasCostMethodAbi, + + chInitialised: make(chan struct{}), + chStop: make(chan struct{}), + chDone: make(chan struct{}), + + isEcotoneMethodAbi: isEcotoneMethodAbi, + + l1BaseFeeCalldata: l1BaseFeeCalldata, + isEcotoneCalldata: isEcotoneCalldata, + getL1GasUsedCalldata: getL1GasUsedCalldata, + getL1FeeCalldata: getL1FeeCalldata, + + isEcotone: false, + isEcotoneCheckTs: 0, + } +} + +func (o *OptimismL1Oracle) Name() string { + return o.logger.Name() +} + +func (o *OptimismL1Oracle) Start(ctx context.Context) error { + return o.StartOnce(o.Name(), func() error { + go o.run() + <-o.chInitialised + return nil + }) +} +func (o *OptimismL1Oracle) Close() error { + return o.StopOnce(o.Name(), func() error { + close(o.chStop) + <-o.chDone + return nil + }) +} + +func (o *OptimismL1Oracle) HealthReport() map[string]error { + return map[string]error{o.Name(): o.Healthy()} +} + +func (o *OptimismL1Oracle) run() { + defer close(o.chDone) + + t := o.refresh() + close(o.chInitialised) + + for { + select { + case <-o.chStop: + return + case <-t.C: + t = o.refresh() + } + } +} +func (o *OptimismL1Oracle) refresh() (t *time.Timer) { + t, err := o.refreshWithError() + if err != nil { + o.SvcErrBuffer.Append(err) + } + return +} + +func (o *OptimismL1Oracle) refreshWithError() (t *time.Timer, err error) { + t = time.NewTimer(utils.WithJitter(o.pollPeriod)) + + ctx, cancel := o.chStop.CtxCancel(evmclient.ContextWithDefaultTimeout()) + defer cancel() + + price, err := o.GetDAGasPrice(ctx) + if err != nil { + return t, err + } + + o.l1GasPriceMu.Lock() + defer o.l1GasPriceMu.Unlock() + o.l1GasPrice = priceEntry{price: assets.NewWei(price), timestamp: time.Now()} + return +} + +func (o *OptimismL1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { + var timestamp time.Time + ok := o.IfStarted(func() { + o.l1GasPriceMu.RLock() + l1GasPrice = o.l1GasPrice.price + timestamp = o.l1GasPrice.timestamp + o.l1GasPriceMu.RUnlock() + }) + if !ok { + return l1GasPrice, fmt.Errorf("L1GasOracle is not started; cannot estimate gas") + } + if l1GasPrice == nil { + return l1GasPrice, fmt.Errorf("failed to get l1 gas price; gas price not set") + } + // Validate the price has been updated within the pollPeriod * 2 + // Allowing double the poll period before declaring the price stale to give ample time for the refresh to process + if time.Since(timestamp) > o.pollPeriod*2 { + return l1GasPrice, fmt.Errorf("gas price is stale") + } + return +} + +// Gets the L1 gas cost for the provided transaction at the specified block num +// If block num is not provided, the value on the latest block num is used +func (o *OptimismL1Oracle) GetGasCost(ctx context.Context, tx *gethtypes.Transaction, blockNum *big.Int) (*assets.Wei, error) { + ctx, cancel := context.WithTimeout(ctx, client.QueryTimeout) + defer cancel() + var callData, b []byte + var err error + if o.chainType == config.ChainKroma { + return nil, fmt.Errorf("L1 gas cost not supported for this chain: %s", o.chainType) + } + // Append rlp-encoded tx + var encodedtx []byte + if encodedtx, err = tx.MarshalBinary(); err != nil { + return nil, fmt.Errorf("failed to marshal tx for gas cost estimation: %w", err) + } + if callData, err = o.l1GasCostMethodAbi.Pack(o.gasCostMethod, encodedtx); err != nil { + return nil, fmt.Errorf("failed to pack calldata for %s L1 gas cost estimation method: %w", o.chainType, err) + } + + precompile := common.HexToAddress(o.l1OracleAddress) + b, err = o.client.CallContract(ctx, ethereum.CallMsg{ + To: &precompile, + Data: callData, + }, blockNum) + if err != nil { + errorMsg := fmt.Sprintf("gas oracle contract call failed: %v", err) + o.logger.Errorf(errorMsg) + return nil, fmt.Errorf(errorMsg) + } + + var l1GasCost *big.Int + if len(b) != 32 { // returns uint256; + errorMsg := fmt.Sprintf("return data length (%d) different than expected (%d)", len(b), 32) + o.logger.Critical(errorMsg) + return nil, fmt.Errorf(errorMsg) + } + l1GasCost = new(big.Int).SetBytes(b) + + return assets.NewWei(l1GasCost), nil +} + +func (o *OptimismL1Oracle) GetDAGasPrice(ctx context.Context) (*big.Int, error) { + isEcotone, err := o.checkIsEcotone(ctx) + if err != nil { + return nil, err + } + + o.logger.Infof("Chain isEcotone result: %t", isEcotone) + + if isEcotone { + return o.getEcotoneGasPrice(ctx) + } + + return o.getV1GasPrice(ctx) +} + +func (o *OptimismL1Oracle) checkIsEcotone(ctx context.Context) (bool, error) { + // if chain is already Ecotone, NOOP + if o.isEcotone { + return true, nil + } + // if time since last check has not exceeded polling period, NOOP + if time.Now().Unix()-o.isEcotoneCheckTs < OPStackGasOracle_isEcotonePollingPeriod { + return false, nil + } + o.isEcotoneCheckTs = time.Now().Unix() + + l1OracleAddress := common.HexToAddress(o.l1OracleAddress) + // confirmed with OP team that isEcotone() is the canonical way to check if the chain has upgraded + b, err := o.client.CallContract(ctx, ethereum.CallMsg{ + To: &l1OracleAddress, + Data: o.isEcotoneCalldata, + }, nil) + + // if the chain has not upgraded to Ecotone, the isEcotone call will revert, this would be expected + if err != nil { + o.logger.Infof("isEcotone() call failed, this can happen if chain has not upgraded: %w", err) + return false, nil + } + + res, err := o.isEcotoneMethodAbi.Unpack(OPStackGasOracle_isEcotone, b) + if err != nil { + return false, fmt.Errorf("failed to unpack isEcotone() return data: %w", err) + } + o.isEcotone = res[0].(bool) + return o.isEcotone, nil +} + +func (o *OptimismL1Oracle) getV1GasPrice(ctx context.Context) (*big.Int, error) { + l1OracleAddress := common.HexToAddress(o.l1OracleAddress) + b, err := o.client.CallContract(ctx, ethereum.CallMsg{ + To: &l1OracleAddress, + Data: o.l1BaseFeeCalldata, + }, nil) + if err != nil { + return nil, fmt.Errorf("l1BaseFee() call failed: %w", err) + } + + if len(b) != 32 { + return nil, fmt.Errorf("l1BaseFee() return data length (%d) different than expected (%d)", len(b), 32) + } + return new(big.Int).SetBytes(b), nil +} + +func (o *OptimismL1Oracle) getEcotoneGasPrice(ctx context.Context) (*big.Int, error) { + rpcBatchCalls := []rpc.BatchElem{ + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.getL1GasUsedCalldata), + }, + "latest", + }, + Result: new(string), + }, + { + Method: "eth_call", + Args: []any{ + map[string]interface{}{ + "from": common.Address{}, + "to": o.l1OracleAddress, + "data": hexutil.Bytes(o.getL1FeeCalldata), + }, + "latest", + }, + Result: new(string), + }, + } + + err := o.client.BatchCallContext(ctx, rpcBatchCalls) + if err != nil { + return nil, fmt.Errorf("getEcotoneGasPrice batch call failed: %w", err) + } + if rpcBatchCalls[0].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", OPStackGasOracle_getL1GasUsed, err) + } + if rpcBatchCalls[1].Error != nil { + return nil, fmt.Errorf("%s call failed in a batch: %w", OPStackGasOracle_getL1Fee, err) + } + + l1GasUsedResult := *(rpcBatchCalls[0].Result.(*string)) + l1FeeResult := *(rpcBatchCalls[1].Result.(*string)) + + l1GasUsedBytes, err := hexutil.Decode(l1GasUsedResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1GasUsed, err) + } + l1FeeBytes, err := hexutil.Decode(l1FeeResult) + if err != nil { + return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1Fee, err) + } + + l1GasUsed := new(big.Int).SetBytes(l1GasUsedBytes) + l1Fee := new(big.Int).SetBytes(l1FeeBytes) + + // for the same tx byte, l1Fee / l1GasUsed will give the l1 gas price + // note this price is per l1 gas, not l1 data byte + return new(big.Int).Div(l1Fee, l1GasUsed), nil +} diff --git a/core/chains/evm/gas/rollups/op_price_reader_test.go b/core/chains/evm/gas/rollups/op_l1_oracle_test.go similarity index 90% rename from core/chains/evm/gas/rollups/op_price_reader_test.go rename to core/chains/evm/gas/rollups/op_l1_oracle_test.go index dad12a16366..36e8700faff 100644 --- a/core/chains/evm/gas/rollups/op_price_reader_test.go +++ b/core/chains/evm/gas/rollups/op_l1_oracle_test.go @@ -60,7 +60,7 @@ func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) call := ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -87,7 +87,7 @@ func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() } - oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) gasPrice, err := oracle.GetDAGasPrice(testutils.Context(t)) if tc.returnBadData { @@ -100,13 +100,13 @@ func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { } } -func setupIsEcotone(t *testing.T, oracleAddress string) *mocks.ETHClient { +func setupIsEcotone(t *testing.T, oracleAddress string) *mocks.L1OracleClient { isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) require.NoError(t, err) isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) require.NoError(t, err) - ethClient := mocks.NewETHClient(t) + ethClient := mocks.NewL1OracleClient(t) ethClient.On("CallContract", mock.Anything, mock.IsType(ethereum.CallMsg{}), mock.IsType(&big.Int{})).Run(func(args mock.Arguments) { callMsg := args.Get(1).(ethereum.CallMsg) blockNumber := args.Get(2).(*big.Int) @@ -142,7 +142,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { for _, rE := range rpcElements { require.Equal(t, "eth_call", rE.Method) - require.Equal(t, oracleAddress, rE.Args[0].(map[string]interface{})["to"].(common.Address).String()) + require.Equal(t, oracleAddress, rE.Args[0].(map[string]interface{})["to"]) require.Equal(t, "latest", rE.Args[1]) } @@ -155,7 +155,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &res2 }).Return(nil).Once() - oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) gasPrice, err := oracle.GetDAGasPrice(testutils.Context(t)) require.NoError(t, err) assert.Equal(t, l1BaseFee, gasPrice) @@ -170,7 +170,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Result = &badData }).Return(nil).Once() - oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(testutils.Context(t)) assert.Error(t, err) }) @@ -179,7 +179,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { ethClient := setupIsEcotone(t, oracleAddress) ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Return(fmt.Errorf("revert")).Once() - oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(testutils.Context(t)) assert.Error(t, err) }) @@ -193,7 +193,7 @@ func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { rpcElements[1].Error = fmt.Errorf("revert") }).Return(nil).Once() - oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + oracle := newOpStackL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) _, err := oracle.GetDAGasPrice(testutils.Context(t)) assert.Error(t, err) }) diff --git a/core/chains/evm/gas/rollups/op_price_reader.go b/core/chains/evm/gas/rollups/op_price_reader.go deleted file mode 100644 index 2d3d668ad8b..00000000000 --- a/core/chains/evm/gas/rollups/op_price_reader.go +++ /dev/null @@ -1,228 +0,0 @@ -package rollups - -import ( - "context" - "fmt" - "math/big" - "strings" - "time" - - "github.com/ethereum/go-ethereum" - "github.com/ethereum/go-ethereum/accounts/abi" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/rpc" - - "github.com/smartcontractkit/chainlink-common/pkg/logger" - - "github.com/smartcontractkit/chainlink/v2/common/config" -) - -const ( - // OPStackGasOracle_l1BaseFee fetches the l1 base fee set in the OP Stack GasPriceOracle contract - OPStackGasOracle_l1BaseFee = "l1BaseFee" - - // OPStackGasOracle_isEcotone fetches if the OP Stack GasPriceOracle contract has upgraded to Ecotone - OPStackGasOracle_isEcotone = "isEcotone" - - // OPStackGasOracle_getL1GasUsed fetches the l1 gas used for given tx bytes - OPStackGasOracle_getL1GasUsed = "getL1GasUsed" - - // OPStackGasOracle_getL1Fee fetches the l1 fee for given tx bytes - OPStackGasOracle_getL1Fee = "getL1Fee" - - // OPStackGasOracle_isEcotonePollingPeriod is the interval to poll if chain has upgraded to Ecotone - // Set to poll every 4 hours - OPStackGasOracle_isEcotonePollingPeriod = 14400 -) - -type opStackGasPriceReader struct { - client ethClient - logger logger.SugaredLogger - - oracleAddress common.Address - isEcotoneMethodAbi abi.ABI - - l1BaseFeeCalldata []byte - isEcotoneCalldata []byte - getL1GasUsedCalldata []byte - getL1FeeCalldata []byte - - isEcotone bool - isEcotoneCheckTs int64 -} - -func newOPPriceReader(lggr logger.Logger, ethClient ethClient, chainType config.ChainType, oracleAddress string) daPriceReader { - // encode calldata for each method; these calldata will remain the same for each call, we can encode them just once - l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) - } - l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(OPStackGasOracle_l1BaseFee) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_l1BaseFee, chainType, err)) - } - - isEcotoneMethodAbi, err := abi.JSON(strings.NewReader(OPIsEcotoneAbiString)) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) - } - isEcotoneCalldata, err := isEcotoneMethodAbi.Pack(OPStackGasOracle_isEcotone) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_isEcotone, chainType, err)) - } - - getL1GasUsedMethodAbi, err := abi.JSON(strings.NewReader(OPGetL1GasUsedAbiString)) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) - } - getL1GasUsedCalldata, err := getL1GasUsedMethodAbi.Pack(OPStackGasOracle_getL1GasUsed, []byte{0x1}) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1GasUsed, chainType, err)) - } - - getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() method ABI for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) - } - getL1FeeCalldata, err := getL1FeeMethodAbi.Pack(OPStackGasOracle_getL1Fee, []byte{0x1}) - if err != nil { - panic(fmt.Errorf("failed to parse GasPriceOracle %s() calldata for chain: %s; %w", OPStackGasOracle_getL1Fee, chainType, err)) - } - - return &opStackGasPriceReader{ - client: ethClient, - logger: logger.Sugared(logger.Named(lggr, fmt.Sprintf("OPStackGasOracle(%s)", chainType))), - - oracleAddress: common.HexToAddress(oracleAddress), - isEcotoneMethodAbi: isEcotoneMethodAbi, - - l1BaseFeeCalldata: l1BaseFeeCalldata, - isEcotoneCalldata: isEcotoneCalldata, - getL1GasUsedCalldata: getL1GasUsedCalldata, - getL1FeeCalldata: getL1FeeCalldata, - - isEcotone: false, - isEcotoneCheckTs: 0, - } -} - -func (o *opStackGasPriceReader) GetDAGasPrice(ctx context.Context) (*big.Int, error) { - isEcotone, err := o.checkIsEcotone(ctx) - if err != nil { - return nil, err - } - - o.logger.Infof("Chain isEcotone result: %t", isEcotone) - - if isEcotone { - return o.getEcotoneGasPrice(ctx) - } - - return o.getV1GasPrice(ctx) -} - -func (o *opStackGasPriceReader) checkIsEcotone(ctx context.Context) (bool, error) { - // if chain is already Ecotone, NOOP - if o.isEcotone { - return true, nil - } - // if time since last check has not exceeded polling period, NOOP - if time.Now().Unix()-o.isEcotoneCheckTs < OPStackGasOracle_isEcotonePollingPeriod { - return false, nil - } - o.isEcotoneCheckTs = time.Now().Unix() - - // confirmed with OP team that isEcotone() is the canonical way to check if the chain has upgraded - b, err := o.client.CallContract(ctx, ethereum.CallMsg{ - To: &o.oracleAddress, - Data: o.isEcotoneCalldata, - }, nil) - - // if the chain has not upgraded to Ecotone, the isEcotone call will revert, this would be expected - if err != nil { - o.logger.Infof("isEcotone() call failed, this can happen if chain has not upgraded: %w", err) - return false, nil - } - - res, err := o.isEcotoneMethodAbi.Unpack(OPStackGasOracle_isEcotone, b) - if err != nil { - return false, fmt.Errorf("failed to unpack isEcotone() return data: %w", err) - } - o.isEcotone = res[0].(bool) - return o.isEcotone, nil -} - -func (o *opStackGasPriceReader) getV1GasPrice(ctx context.Context) (*big.Int, error) { - b, err := o.client.CallContract(ctx, ethereum.CallMsg{ - To: &o.oracleAddress, - Data: o.l1BaseFeeCalldata, - }, nil) - if err != nil { - return nil, fmt.Errorf("l1BaseFee() call failed: %w", err) - } - - if len(b) != 32 { - return nil, fmt.Errorf("l1BaseFee() return data length (%d) different than expected (%d)", len(b), 32) - } - return new(big.Int).SetBytes(b), nil -} - -func (o *opStackGasPriceReader) getEcotoneGasPrice(ctx context.Context) (*big.Int, error) { - rpcBatchCalls := []rpc.BatchElem{ - { - Method: "eth_call", - Args: []any{ - map[string]interface{}{ - "from": common.Address{}, - "to": o.oracleAddress, - "data": hexutil.Bytes(o.getL1GasUsedCalldata), - }, - "latest", - }, - Result: new(string), - }, - { - Method: "eth_call", - Args: []any{ - map[string]interface{}{ - "from": common.Address{}, - "to": o.oracleAddress, - "data": hexutil.Bytes(o.getL1FeeCalldata), - }, - "latest", - }, - Result: new(string), - }, - } - - err := o.client.BatchCallContext(ctx, rpcBatchCalls) - if err != nil { - return nil, fmt.Errorf("getEcotoneGasPrice batch call failed: %w", err) - } - if rpcBatchCalls[0].Error != nil { - return nil, fmt.Errorf("%s call failed in a batch: %w", OPStackGasOracle_getL1GasUsed, err) - } - if rpcBatchCalls[1].Error != nil { - return nil, fmt.Errorf("%s call failed in a batch: %w", OPStackGasOracle_getL1Fee, err) - } - - l1GasUsedResult := *(rpcBatchCalls[0].Result.(*string)) - l1FeeResult := *(rpcBatchCalls[1].Result.(*string)) - - l1GasUsedBytes, err := hexutil.Decode(l1GasUsedResult) - if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1GasUsed, err) - } - l1FeeBytes, err := hexutil.Decode(l1FeeResult) - if err != nil { - return nil, fmt.Errorf("failed to decode %s rpc result: %w", OPStackGasOracle_getL1Fee, err) - } - - l1GasUsed := new(big.Int).SetBytes(l1GasUsedBytes) - l1Fee := new(big.Int).SetBytes(l1FeeBytes) - - // for the same tx byte, l1Fee / l1GasUsed will give the l1 gas price - // note this price is per l1 gas, not l1 data byte - return new(big.Int).Div(l1Fee, l1GasUsed), nil -} diff --git a/core/chains/evm/gas/suggested_price_estimator.go b/core/chains/evm/gas/suggested_price_estimator.go index edc1b0f92fa..e947e9109d1 100644 --- a/core/chains/evm/gas/suggested_price_estimator.go +++ b/core/chains/evm/gas/suggested_price_estimator.go @@ -19,6 +19,7 @@ import ( feetypes "github.com/smartcontractkit/chainlink/v2/common/fee/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) @@ -31,8 +32,7 @@ type suggestedPriceConfig interface { BumpMin() *assets.Wei } -//go:generate mockery --quiet --name rpcClient --output ./mocks/ --case=underscore --structname RPCClient -type rpcClient interface { +type suggestedPriceEstimatorClient interface { CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error } @@ -41,7 +41,7 @@ type SuggestedPriceEstimator struct { services.StateMachine cfg suggestedPriceConfig - client rpcClient + client suggestedPriceEstimatorClient pollPeriod time.Duration logger logger.Logger @@ -52,10 +52,12 @@ type SuggestedPriceEstimator struct { chInitialised chan struct{} chStop services.StopChan chDone chan struct{} + + l1Oracle rollups.L1Oracle } // NewSuggestedPriceEstimator returns a new Estimator which uses the suggested gas price. -func NewSuggestedPriceEstimator(lggr logger.Logger, client rpcClient, cfg suggestedPriceConfig) EvmEstimator { +func NewSuggestedPriceEstimator(lggr logger.Logger, client feeEstimatorClient, cfg suggestedPriceConfig, l1Oracle rollups.L1Oracle) EvmEstimator { return &SuggestedPriceEstimator{ client: client, pollPeriod: 10 * time.Second, @@ -65,6 +67,7 @@ func NewSuggestedPriceEstimator(lggr logger.Logger, client rpcClient, cfg sugges chInitialised: make(chan struct{}), chStop: make(chan struct{}), chDone: make(chan struct{}), + l1Oracle: l1Oracle, } } @@ -72,6 +75,10 @@ func (o *SuggestedPriceEstimator) Name() string { return o.logger.Name() } +func (o *SuggestedPriceEstimator) L1Oracle() rollups.L1Oracle { + return o.l1Oracle +} + func (o *SuggestedPriceEstimator) Start(context.Context) error { return o.StartOnce("SuggestedPriceEstimator", func() error { go o.run() diff --git a/core/chains/evm/gas/suggested_price_estimator_test.go b/core/chains/evm/gas/suggested_price_estimator_test.go index 0d52d6ab1b9..4f3c4d307d6 100644 --- a/core/chains/evm/gas/suggested_price_estimator_test.go +++ b/core/chains/evm/gas/suggested_price_estimator_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/mocks" + rollupMocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/gas/rollups/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" ) @@ -29,20 +30,24 @@ func TestSuggestedPriceEstimator(t *testing.T) { cfg := &gas.MockGasEstimatorConfig{BumpPercentF: 10, BumpMinF: assets.NewWei(big.NewInt(1)), BumpThresholdF: 1} t.Run("calling GetLegacyGas on unstarted estimator returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) _, _, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) assert.EqualError(t, err, "estimator is not started") }) t.Run("calling GetLegacyGas on started estimator returns prices", func(t *testing.T) { - client := mocks.NewRPCClient(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.GetLegacyGas(testutils.Context(t), calldata, gasLimit, maxGasPrice) require.NoError(t, err) @@ -51,10 +56,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("gas price is lower than user specified max gas price", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) @@ -68,10 +75,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("gas price is lower than global max gas price", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(120) }) @@ -84,10 +93,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling GetLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) servicetest.RunHealthy(t, o) @@ -96,22 +107,28 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling GetDynamicFee always returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) _, err := o.GetDynamicFee(testutils.Context(t), maxGasPrice) assert.EqualError(t, err, "dynamic fees are not implemented for this estimator") }) t.Run("calling BumpLegacyGas on unstarted estimator returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) _, _, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(42), gasLimit, maxGasPrice, nil) assert.EqualError(t, err, "estimator is not started") }) t.Run("calling BumpDynamicFee always returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) fee := gas.DynamicFee{ FeeCap: assets.NewWeiI(42), TipCap: assets.NewWeiI(5), @@ -121,13 +138,15 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator returns new price buffered with bumpPercent", func(t *testing.T) { - client := mocks.NewRPCClient(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(40) }) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil) require.NoError(t, err) @@ -136,14 +155,16 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator returns new price buffered with bumpMin", func(t *testing.T) { - client := mocks.NewRPCClient(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(40) }) - testCfg := &gas.MockGasEstimatorConfig{BumpPercentF: 1, BumpMinF: assets.NewWei(big.NewInt(1)), BumpThresholdF: 1} - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, testCfg) + testCfg := &gas.MockGasEstimatorConfig{BumpPercentF: 1, BumpMinF: assets.NewWei(big.NewInt(1)), BumpThresholdF: 1, LimitMultiplierF: 1} + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, testCfg, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil) require.NoError(t, err) @@ -152,13 +173,15 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator returns original price when lower than previous", func(t *testing.T) { - client := mocks.NewRPCClient(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(5) }) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) servicetest.RunHealthy(t, o) gasPrice, chainSpecificGasLimit, err := o.BumpLegacyGas(testutils.Context(t), assets.NewWeiI(10), gasLimit, maxGasPrice, nil) require.NoError(t, err) @@ -167,10 +190,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator returns error, suggested gas price is higher than max gas price", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(42) }) @@ -184,10 +209,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator returns max gas price when suggested price under max but the buffer exceeds it", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) + + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(39) }) @@ -200,10 +227,12 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator if initial call failed returns error", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) servicetest.RunHealthy(t, o) @@ -212,14 +241,16 @@ func TestSuggestedPriceEstimator(t *testing.T) { }) t.Run("calling BumpLegacyGas on started estimator if refresh call failed returns price from previous update", func(t *testing.T) { - client := mocks.NewRPCClient(t) - o := gas.NewSuggestedPriceEstimator(logger.Test(t), client, cfg) + feeEstimatorClient := mocks.NewFeeEstimatorClient(t) + l1Oracle := rollupMocks.NewL1Oracle(t) + + o := gas.NewSuggestedPriceEstimator(logger.Test(t), feeEstimatorClient, cfg, l1Oracle) - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(nil).Run(func(args mock.Arguments) { res := args.Get(1).(*hexutil.Big) (*big.Int)(res).SetInt64(40) }).Once() - client.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) + feeEstimatorClient.On("CallContext", mock.Anything, mock.Anything, "eth_gasPrice").Return(pkgerrors.New("kaboom")) servicetest.RunHealthy(t, o) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 3500002e8da..070c2c37473 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -64,9 +64,9 @@ func NewTestEthBroadcaster( lggr := logger.Test(t) ge := config.EVM().GasEstimator() - estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { - return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), ge.BlockHistory(), lggr) - }, ge.EIP1559DynamicFees(), nil, ge) + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(config.EVM().GasEstimator(), nil, ge.BlockHistory(), lggr, nil) + }, ge.EIP1559DynamicFees(), ge) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, keyStore, estimator) ethBroadcaster := txmgrcommon.NewBroadcaster(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(config.EVM().GasEstimator()), config.EVM().Transactions(), config.Database().Listener(), keyStore, txBuilder, nonceTracker, lggr, checkerFactory, nonceAutoSync) @@ -1152,9 +1152,9 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { // same as the parent test, but callback is set by ctor t.Run("callback set by ctor", func(t *testing.T) { - estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { - return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil, evmcfg.EVM().GasEstimator()) + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) localNextNonce = getLocalNextNonce(t, nonceTracker, fromAddress) eb2 := txmgr.NewEvmBroadcaster(txStore, txmClient, txmgr.NewEvmTxmConfig(evmcfg.EVM()), txmgr.NewEvmTxmFeeConfig(evmcfg.EVM().GasEstimator()), evmcfg.EVM().Transactions(), evmcfg.Database().Listener(), ethKeyStore, txBuilder, lggr, &testCheckerFactory{}, false) @@ -1738,9 +1738,9 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { kst := cltest.NewKeyStore(t, db, cfg.Database()).Eth() _, fromAddress := cltest.RandomKey{Disabled: false}.MustInsertWithState(t, kst) - estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { - return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), evmcfg.EVM().GasEstimator().BlockHistory(), lggr) - }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), nil, evmcfg.EVM().GasEstimator()) + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(evmcfg.EVM().GasEstimator(), nil, evmcfg.EVM().GasEstimator().BlockHistory(), lggr, nil) + }, evmcfg.EVM().GasEstimator().EIP1559DynamicFees(), evmcfg.EVM().GasEstimator()) checkerFactory := &testCheckerFactory{} ge := evmcfg.EVM().GasEstimator() diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 357dafcbdc4..89e88d5a6dc 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -127,7 +127,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { newEst := func(logger.Logger) gas.EvmEstimator { return estimator } lggr := logger.Test(t) ge := config.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ethKeyStore, feeEstimator) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ethKeyStore, txBuilder, lggr) ctx := testutils.Context(t) @@ -1647,7 +1647,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing newEst := func(logger.Logger) gas.EvmEstimator { return estimator } estimator.On("BumpLegacyGas", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, uint64(0), pkgerrors.Wrapf(commonfee.ErrConnectivity, "transaction...")) ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -1695,7 +1695,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing newEst := func(logger.Logger) gas.EvmEstimator { return estimator } // Create confirmer with necessary state ge := ccfg.EVM().GasEstimator() - feeEstimator := gas.NewWrappedEvmEstimator(lggr, newEst, ge.EIP1559DynamicFees(), nil, ge) + feeEstimator := gas.NewEvmFeeEstimator(lggr, newEst, ge.EIP1559DynamicFees(), ge) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, kst, feeEstimator) addresses := []gethCommon.Address{fromAddress} kst.On("EnabledAddressesForChain", mock.Anything, &cltest.FixtureChainID).Return(addresses, nil).Maybe() @@ -3133,9 +3133,9 @@ func ptr[T any](t T) *T { return &t } func newEthConfirmer(t testing.TB, txStore txmgr.EvmTxStore, ethClient client.Client, config evmconfig.ChainScopedConfig, ks keystore.Eth, fn txmgrcommon.ResumeCallback) *txmgr.Confirmer { lggr := logger.Test(t) ge := config.EVM().GasEstimator() - estimator := gas.NewWrappedEvmEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { - return gas.NewFixedPriceEstimator(ge, ge.BlockHistory(), lggr) - }, ge.EIP1559DynamicFees(), nil, ge) + estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { + return gas.NewFixedPriceEstimator(ge, nil, ge.BlockHistory(), lggr, nil) + }, ge.EIP1559DynamicFees(), ge) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ge, ks, estimator) ec := txmgr.NewEvmConfirmer(txStore, txmgr.NewEvmTxmClient(ethClient), txmgr.NewEvmTxmConfig(config.EVM()), txmgr.NewEvmTxmFeeConfig(ge), config.EVM().Transactions(), config.Database(), ks, txBuilder, lggr) ec.SetResumeCallback(fn) From 8337fc821baf8011c6c73203482db85f5a44d7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Thu, 18 Apr 2024 20:24:43 +0300 Subject: [PATCH 08/26] Keystone refactoring (#12880) * Try a simple change * Regenerate keystone wrappers * Add changesets * Remove Keystone gas tests * Remove parenthesis --- .changeset/great-rockets-obey.md | 5 +++++ .github/workflows/solidity-foundry.yml | 2 +- contracts/.changeset/mean-items-talk.md | 5 +++++ contracts/gas-snapshots/keystone.gas-snapshot | 2 -- contracts/src/v0.8/keystone/KeystoneForwarder.sol | 12 +++++++++++- .../keystone/generated/forwarder/forwarder.go | 4 ++-- ...rated-wrapper-dependency-versions-do-not-edit.txt | 2 +- 7 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 .changeset/great-rockets-obey.md create mode 100644 contracts/.changeset/mean-items-talk.md delete mode 100644 contracts/gas-snapshots/keystone.gas-snapshot diff --git a/.changeset/great-rockets-obey.md b/.changeset/great-rockets-obey.md new file mode 100644 index 00000000000..b90bc810a01 --- /dev/null +++ b/.changeset/great-rockets-obey.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#wip Keystone wrapper regenerate diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index cea16f45f16..2d62ef864a5 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -79,7 +79,7 @@ jobs: FOUNDRY_PROFILE: ${{ matrix.product }} - name: Run Forge snapshot - if: ${{ !contains(fromJson('["vrf"]'), matrix.product) && !contains(fromJson('["automation"]'), matrix.product) && needs.changes.outputs.changes == 'true' }} + if: ${{ !contains(fromJson('["vrf"]'), matrix.product) && !contains(fromJson('["automation"]'), matrix.product) && !contains(fromJson('["keystone"]'), matrix.product) && needs.changes.outputs.changes == 'true' }} run: | forge snapshot --nmt "testFuzz_\w{1,}?" --check gas-snapshots/${{ matrix.product }}.gas-snapshot id: snapshot diff --git a/contracts/.changeset/mean-items-talk.md b/contracts/.changeset/mean-items-talk.md new file mode 100644 index 00000000000..e03d49335ad --- /dev/null +++ b/contracts/.changeset/mean-items-talk.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#wip Keystone custom error diff --git a/contracts/gas-snapshots/keystone.gas-snapshot b/contracts/gas-snapshots/keystone.gas-snapshot deleted file mode 100644 index 6797bd77e20..00000000000 --- a/contracts/gas-snapshots/keystone.gas-snapshot +++ /dev/null @@ -1,2 +0,0 @@ -KeystoneForwarderTest:test_abi_partial_decoding_works() (gas: 5123) -KeystoneForwarderTest:test_it_works() (gas: 996215) \ No newline at end of file diff --git a/contracts/src/v0.8/keystone/KeystoneForwarder.sol b/contracts/src/v0.8/keystone/KeystoneForwarder.sol index b4a9501e8f4..e6e2675fa2d 100644 --- a/contracts/src/v0.8/keystone/KeystoneForwarder.sol +++ b/contracts/src/v0.8/keystone/KeystoneForwarder.sol @@ -10,6 +10,14 @@ import {Utils} from "./libraries/Utils.sol"; contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterface { error ReentrantCall(); + /// @notice This error is returned when the data with report is invalid. + /// This can happen if the data is shorter than SELECTOR_LENGTH + REPORT_LENGTH. + /// @param data the data that was received + error InvalidData(bytes data); + + uint256 private constant SELECTOR_LENGTH = 4; + uint256 private constant REPORT_LENGTH = 64; + struct HotVars { bool reentrancyGuard; // guard against reentrancy } @@ -26,7 +34,9 @@ contract KeystoneForwarder is IForwarder, ConfirmedOwner, TypeAndVersionInterfac bytes calldata data, bytes[] calldata signatures ) external nonReentrant returns (bool) { - require(data.length > 4 + 64, "invalid data length"); + if (data.length < SELECTOR_LENGTH + REPORT_LENGTH) { + revert InvalidData(data); + } // data is an encoded call with the selector prefixed: (bytes4 selector, bytes report, ...) // we are able to partially decode just the first param, since we don't know the rest diff --git a/core/gethwrappers/keystone/generated/forwarder/forwarder.go b/core/gethwrappers/keystone/generated/forwarder/forwarder.go index c66e2886793..c8cf31ae869 100644 --- a/core/gethwrappers/keystone/generated/forwarder/forwarder.go +++ b/core/gethwrappers/keystone/generated/forwarder/forwarder.go @@ -31,8 +31,8 @@ var ( ) var KeystoneForwarderMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"targetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610c12806101576000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063c0965dc311610050578063c0965dc314610108578063e6b714581461012b578063f2fde38b1461016157600080fd5b8063181f5a771461007757806379ba5097146100bf5780638da5cb5b146100c9575b600080fd5b604080518082018252601781527f4b657973746f6e65466f7277617264657220312e302e30000000000000000000602082015290516100b69190610827565b60405180910390f35b6100c7610174565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b6565b61011b6101163660046108bc565b610276565b60405190151581526020016100b6565b6100e3610139366004610998565b60009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b6100c761016f3660046109b1565b61058e565b60015473ffffffffffffffffffffffffffffffffffffffff1633146101fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60025460009060ff16156102b6576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556044841161034b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f696e76616c69642064617461206c656e6774680000000000000000000000000060448201526064016101f1565b600061035a85600481896109d3565b8101906103679190610a2c565b8051602082012090915060005b848110156104655760008060006103e289898681811061039657610396610afb565b90506020028101906103a89190610b2a565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506105a292505050565b925092509250600060018683868660405160008152602001604052604051610426949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610448573d6000803e3d6000fd5b5086955061045d9450859350610b9692505050565b915050610374565b5060008061047284610630565b600081815260036020526040902054919350915073ffffffffffffffffffffffffffffffffffffffff16156104ae57600094505050505061055d565b6000808b73ffffffffffffffffffffffffffffffffffffffff168b8b6040516104d8929190610bf5565b6000604051808303816000865af19150503d8060008114610515576040519150601f19603f3d011682016040523d82523d6000602084013e61051a565b606091505b5050506000928352505060036020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055506001925050505b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905595945050505050565b6105966106af565b61059f81610732565b50565b60008060008351604114610612576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e677468000000000000000060448201526064016101f1565b50505060208101516040820151606090920151909260009190911a90565b600080604083511161069e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e76616c6964207265706f7274206c656e677468000000000000000000000060448201526064016101f1565b505060208101516040909101519091565b60005473ffffffffffffffffffffffffffffffffffffffff163314610730576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016101f1565b565b3373ffffffffffffffffffffffffffffffffffffffff8216036107b1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016101f1565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b8181101561085457858101830151858201604001528201610838565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146108b757600080fd5b919050565b6000806000806000606086880312156108d457600080fd5b6108dd86610893565b9450602086013567ffffffffffffffff808211156108fa57600080fd5b818801915088601f83011261090e57600080fd5b81358181111561091d57600080fd5b89602082850101111561092f57600080fd5b60208301965080955050604088013591508082111561094d57600080fd5b818801915088601f83011261096157600080fd5b81358181111561097057600080fd5b8960208260051b850101111561098557600080fd5b9699959850939650602001949392505050565b6000602082840312156109aa57600080fd5b5035919050565b6000602082840312156109c357600080fd5b6109cc82610893565b9392505050565b600080858511156109e357600080fd5b838611156109f057600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610a3e57600080fd5b813567ffffffffffffffff80821115610a5657600080fd5b818401915084601f830112610a6a57600080fd5b813581811115610a7c57610a7c6109fd565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610ac257610ac26109fd565b81604052828152876020848701011115610adb57600080fd5b826020860160208301376000928101602001929092525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610b5f57600080fd5b83018035915067ffffffffffffffff821115610b7a57600080fd5b602001915036819003821315610b8f57600080fd5b9250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610bee577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b5060010190565b818382376000910190815291905056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"InvalidData\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"workflowExecutionId\",\"type\":\"bytes32\"}],\"name\":\"getTransmitter\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"targetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"},{\"internalType\":\"bytes[]\",\"name\":\"signatures\",\"type\":\"bytes[]\"}],\"name\":\"report\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b610c5f806101576000396000f3fe608060405234801561001057600080fd5b50600436106100725760003560e01c8063c0965dc311610050578063c0965dc314610108578063e6b714581461012b578063f2fde38b1461016157600080fd5b8063181f5a771461007757806379ba5097146100bf5780638da5cb5b146100c9575b600080fd5b604080518082018252601781527f4b657973746f6e65466f7277617264657220312e302e30000000000000000000602082015290516100b69190610806565b60405180910390f35b6100c7610174565b005b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100b6565b61011b61011636600461089b565b610276565b60405190151581526020016100b6565b6100e3610139366004610977565b60009081526003602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b6100c761016f366004610990565b61056d565b60015473ffffffffffffffffffffffffffffffffffffffff1633146101fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60025460009060ff16156102b6576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556102ed604060046109e1565b84101561032a5784846040517f2a62609b0000000000000000000000000000000000000000000000000000000081526004016101f19291906109fa565b60006103398560048189610a47565b8101906103469190610aa0565b8051602082012090915060005b848110156104445760008060006103c189898681811061037557610375610b6f565b90506020028101906103879190610b9e565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061058192505050565b925092509250600060018683868660405160008152602001604052604051610405949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015610427573d6000803e3d6000fd5b5086955061043c9450859350610c0a92505050565b915050610353565b506000806104518461060f565b600081815260036020526040902054919350915073ffffffffffffffffffffffffffffffffffffffff161561048d57600094505050505061053c565b6000808b73ffffffffffffffffffffffffffffffffffffffff168b8b6040516104b7929190610c42565b6000604051808303816000865af19150503d80600081146104f4576040519150601f19603f3d011682016040523d82523d6000602084013e6104f9565b606091505b5050506000928352505060036020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001633179055506001925050505b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905595945050505050565b61057561068e565b61057e81610711565b50565b600080600083516041146105f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f696e76616c6964207369676e6174757265206c656e677468000000000000000060448201526064016101f1565b50505060208101516040820151606090920151909260009190911a90565b600080604083511161067d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f696e76616c6964207265706f7274206c656e677468000000000000000000000060448201526064016101f1565b505060208101516040909101519091565b60005473ffffffffffffffffffffffffffffffffffffffff16331461070f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016101f1565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610790576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016101f1565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b8181101561083357858101830151858201604001528201610817565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461089657600080fd5b919050565b6000806000806000606086880312156108b357600080fd5b6108bc86610872565b9450602086013567ffffffffffffffff808211156108d957600080fd5b818801915088601f8301126108ed57600080fd5b8135818111156108fc57600080fd5b89602082850101111561090e57600080fd5b60208301965080955050604088013591508082111561092c57600080fd5b818801915088601f83011261094057600080fd5b81358181111561094f57600080fd5b8960208260051b850101111561096457600080fd5b9699959850939650602001949392505050565b60006020828403121561098957600080fd5b5035919050565b6000602082840312156109a257600080fd5b6109ab82610872565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156109f4576109f46109b2565b92915050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60008085851115610a5757600080fd5b83861115610a6457600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600060208284031215610ab257600080fd5b813567ffffffffffffffff80821115610aca57600080fd5b818401915084601f830112610ade57600080fd5b813581811115610af057610af0610a71565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610b3657610b36610a71565b81604052828152876020848701011115610b4f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610bd357600080fd5b83018035915067ffffffffffffffff821115610bee57600080fd5b602001915036819003821315610c0357600080fd5b9250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610c3b57610c3b6109b2565b5060010190565b818382376000910190815291905056fea164736f6c6343000813000a", } var KeystoneForwarderABI = KeystoneForwarderMetaData.ABI diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index b9d8bfbfefc..8b1c830405d 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,3 +1,3 @@ GETH_VERSION: 1.13.8 -forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin 4886b538e1fdc8aaf860901de36269e0c35acfd3e6eb190654d693ff9dbd4b6d +forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 From aa5718264bd55e51c4223c31433176e732e8b584 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Thu, 18 Apr 2024 15:04:23 -0500 Subject: [PATCH 09/26] skip tests when -short (#12869) --- .github/workflows/ci-core.yml | 2 ++ .../evm/headtracker/head_listener_test.go | 3 ++ core/chains/evm/log/integration_test.go | 4 +-- core/gethwrappers/go_generate_test.go | 31 ++++++++++++------- .../fluxmonitorv2/contract_submitter_test.go | 1 + .../fluxmonitorv2/flux_monitor_test.go | 8 +++++ .../fluxmonitorv2/payment_checker_test.go | 2 ++ .../fluxmonitorv2/poll_manager_test.go | 14 +++++++++ .../fluxmonitorv2/submission_checker_test.go | 1 + core/services/fluxmonitorv2/validate_test.go | 1 + .../functions/subscriptions/orm_test.go | 1 + .../subscriptions/subscriptions_test.go | 3 ++ .../generic/pipeline_runner_adapter_test.go | 1 + .../v21/mercury/v02/v02_request_test.go | 7 +++++ .../v21/mercury/v03/v03_request_test.go | 6 ++++ core/services/workflows/engine_test.go | 3 ++ core/services/workflows/models_test.go | 1 + core/services/workflows/models_yaml_test.go | 2 ++ core/services/workflows/state_test.go | 2 ++ main_test.go | 3 ++ 20 files changed, 82 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 9eaf31d0ba2..9d9ff595ed0 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -107,6 +107,8 @@ jobs: - name: Setup Go if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-go + - name: Run short tests + run: go test -short ./... - name: Setup Solana if: ${{ needs.filter.outputs.changes == 'true' }} uses: ./.github/actions/setup-solana diff --git a/core/chains/evm/headtracker/head_listener_test.go b/core/chains/evm/headtracker/head_listener_test.go index e5131aca422..4e7efb5e809 100644 --- a/core/chains/evm/headtracker/head_listener_test.go +++ b/core/chains/evm/headtracker/head_listener_test.go @@ -25,6 +25,7 @@ import ( ) func Test_HeadListener_HappyPath(t *testing.T) { + t.Parallel() // Logic: // - spawn a listener instance // - mock SubscribeNewHead/Err/Unsubscribe to track these calls @@ -91,6 +92,7 @@ func Test_HeadListener_HappyPath(t *testing.T) { } func Test_HeadListener_NotReceivingHeads(t *testing.T) { + t.Parallel() // Logic: // - same as Test_HeadListener_HappyPath, but // - send one head, make sure ReceivingHeads() is true @@ -149,6 +151,7 @@ func Test_HeadListener_NotReceivingHeads(t *testing.T) { } func Test_HeadListener_SubscriptionErr(t *testing.T) { + t.Parallel() tests := []struct { name string err error diff --git a/core/chains/evm/log/integration_test.go b/core/chains/evm/log/integration_test.go index 4bdb43d9521..fd6b375d80a 100644 --- a/core/chains/evm/log/integration_test.go +++ b/core/chains/evm/log/integration_test.go @@ -263,8 +263,6 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { log2 := blocks.LogOnBlockNum(log2Block, contract2.Address()) logs := []types.Log{log1, log2} - contract1.On("ParseLog", log1).Return(flux_aggregator_wrapper.FluxAggregatorNewRound{}, nil) - contract2.On("ParseLog", log2).Return(flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{}, nil) t.Run("pool two logs from subscription, then shut down", func(t *testing.T) { helper := newBroadcasterHelper(t, 0, 1, logs, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].FinalityDepth = ptr[uint32](confs) @@ -295,6 +293,8 @@ func TestBroadcaster_BackfillUnconsumedAfterCrash(t *testing.T) { c.EVM[0].FinalityDepth = ptr[uint32](confs) }) orm := log.NewORM(helper.db, cltest.FixtureChainID) + contract1.On("ParseLog", log1).Return(flux_aggregator_wrapper.FluxAggregatorNewRound{}, nil) + contract2.On("ParseLog", log2).Return(flux_aggregator_wrapper.FluxAggregatorAnswerUpdated{}, nil) listener := helper.newLogListenerWithJob("one") listener.SkipMarkingConsumed(true) diff --git a/core/gethwrappers/go_generate_test.go b/core/gethwrappers/go_generate_test.go index 52d0f520dd7..a6253cb1a66 100644 --- a/core/gethwrappers/go_generate_test.go +++ b/core/gethwrappers/go_generate_test.go @@ -4,6 +4,7 @@ package gethwrappers import ( "crypto/sha256" + "flag" "fmt" "os" "os/exec" @@ -15,6 +16,7 @@ import ( "github.com/fatih/color" cutils "github.com/smartcontractkit/chainlink-common/pkg/utils" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/utils" "github.com/stretchr/testify/assert" @@ -27,6 +29,7 @@ const compileCommand = "../../contracts/scripts/native_solc_compile_all" // contract artifacts in contracts/solc with the abi and bytecode stored in the // contract wrapper func TestCheckContractHashesFromLastGoGenerate(t *testing.T) { + testutils.SkipShort(t, "requires compiled artifacts") versions, err := ReadVersionsDB() require.NoError(t, err) require.NotEmpty(t, versions.GethVersion, `version DB should have a "GETH_VERSION:" line`) @@ -63,19 +66,13 @@ func isVRFV2Contract(fullpath string) bool { return strings.Contains(fullpath, "VRFCoordinatorV2") } -// rootDir is the local chainlink root working directory -var rootDir string - -func init() { // compute rootDir - var err error - thisDir, err := os.Getwd() - if err != nil { - panic(err) - } - rootDir, err = filepath.Abs(filepath.Join(thisDir, "../..")) +// getRootDir returns the local chainlink root working directory +func getRootDir() (string, error) { // compute rootDir + wd, err := os.Getwd() if err != nil { - panic(err) + return "", fmt.Errorf("failed to get working directory: %w", err) } + return filepath.Abs(filepath.Join(wd, "../..")) } // compareCurrentCompilerArtifactAgainstRecordsAndSoliditySources checks that @@ -95,6 +92,8 @@ func compareCurrentCompilerArtifactAgainstRecordsAndSoliditySources( t *testing.T, versionInfo ContractVersion, ) { hash := VersionHash(versionInfo.AbiPath, versionInfo.BinaryPath) + rootDir, err := getRootDir() + require.NoError(t, err) recompileCommand := fmt.Sprintf("(cd %s/contracts; make wrappers-all)", rootDir) assert.Equal(t, versionInfo.Hash, hash, utils.BoxOutput(`compiled %s and/or %s has changed; please rerun @@ -102,9 +101,17 @@ func compareCurrentCompilerArtifactAgainstRecordsAndSoliditySources( and commit the changes`, versionInfo.AbiPath, versionInfo.BinaryPath, recompileCommand)) } +func TestMain(m *testing.M) { + flag.Parse() + if !testing.Short() { + ensureArtifacts() + } + os.Exit(m.Run()) +} + // Ensure that solidity compiler artifacts are present before running this test, // by compiling them if necessary. -func init() { +func ensureArtifacts() { db, err := versionsDBLineReader() if err != nil { panic(err) diff --git a/core/services/fluxmonitorv2/contract_submitter_test.go b/core/services/fluxmonitorv2/contract_submitter_test.go index 238cf96e033..7dfd92e5acd 100644 --- a/core/services/fluxmonitorv2/contract_submitter_test.go +++ b/core/services/fluxmonitorv2/contract_submitter_test.go @@ -15,6 +15,7 @@ import ( ) func TestFluxAggregatorContractSubmitter_Submit(t *testing.T) { + t.Parallel() var ( fluxAggregator = mocks.NewFluxAggregator(t) orm = fmmocks.NewORM(t) diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index 042ddb99afb..d8713fed997 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -291,6 +291,7 @@ func setupFullDBWithKey(t *testing.T) (*sqlx.DB, common.Address) { } func TestFluxMonitor_PollIfEligible(t *testing.T) { + t.Parallel() testCases := []struct { name string eligible bool @@ -499,6 +500,7 @@ func TestFluxMonitor_PollIfEligible(t *testing.T) { // If the roundState method is unable to communicate with the contract (possibly due to // incorrect address) then the pollIfEligible method should create a JobErr record func TestFluxMonitor_PollIfEligible_Creates_JobErr(t *testing.T) { + t.Parallel() db, nodeAddr := setupStoreWithKey(t) oracles := []common.Address{nodeAddr, testutils.NewAddress()} @@ -529,6 +531,7 @@ func TestFluxMonitor_PollIfEligible_Creates_JobErr(t *testing.T) { } func TestPollingDeviationChecker_BuffersLogs(t *testing.T) { + t.Parallel() db, nodeAddr := setupStoreWithKey(t) oracles := []common.Address{nodeAddr, testutils.NewAddress()} @@ -728,6 +731,7 @@ func TestPollingDeviationChecker_BuffersLogs(t *testing.T) { } func TestFluxMonitor_TriggerIdleTimeThreshold(t *testing.T) { + t.Parallel() g := gomega.NewWithT(t) testCases := []struct { @@ -904,6 +908,7 @@ func TestFluxMonitor_HibernationTickerFiresMultipleTimes(t *testing.T) { } func TestFluxMonitor_HibernationIsEnteredAndRetryTickerStopped(t *testing.T) { + t.Parallel() db, nodeAddr := setupFullDBWithKey(t) oracles := []common.Address{nodeAddr, testutils.NewAddress()} @@ -1173,6 +1178,7 @@ func TestFluxMonitor_RoundTimeoutCausesPoll_timesOutAtZero(t *testing.T) { } func TestFluxMonitor_UsesPreviousRoundStateOnStartup_RoundTimeout(t *testing.T) { + t.Parallel() g := gomega.NewWithT(t) db, nodeAddr := setupStoreWithKey(t) @@ -1234,6 +1240,7 @@ func TestFluxMonitor_UsesPreviousRoundStateOnStartup_RoundTimeout(t *testing.T) } func TestFluxMonitor_UsesPreviousRoundStateOnStartup_IdleTimer(t *testing.T) { + t.Parallel() g := gomega.NewWithT(t) db, nodeAddr := setupStoreWithKey(t) @@ -1433,6 +1440,7 @@ func TestFluxMonitor_ConsumeLogBroadcast_Error(t *testing.T) { } func TestFluxMonitor_DoesNotDoubleSubmit(t *testing.T) { + t.Parallel() t.Run("when NewRound log arrives, then poll ticker fires", func(t *testing.T) { db, nodeAddr := setupStoreWithKey(t) oracles := []common.Address{nodeAddr, testutils.NewAddress()} diff --git a/core/services/fluxmonitorv2/payment_checker_test.go b/core/services/fluxmonitorv2/payment_checker_test.go index baec5642339..88643a69fb2 100644 --- a/core/services/fluxmonitorv2/payment_checker_test.go +++ b/core/services/fluxmonitorv2/payment_checker_test.go @@ -11,6 +11,7 @@ import ( ) func TestPaymentChecker_SufficientFunds(t *testing.T) { + t.Parallel() var ( checker = fluxmonitorv2.NewPaymentChecker(nil, nil) payment = 100 @@ -44,6 +45,7 @@ func TestPaymentChecker_SufficientFunds(t *testing.T) { } func TestPaymentChecker_SufficientPayment(t *testing.T) { + t.Parallel() var ( payment int64 = 10 eq = payment diff --git a/core/services/fluxmonitorv2/poll_manager_test.go b/core/services/fluxmonitorv2/poll_manager_test.go index 9245c309c27..be6aa9a819b 100644 --- a/core/services/fluxmonitorv2/poll_manager_test.go +++ b/core/services/fluxmonitorv2/poll_manager_test.go @@ -84,6 +84,7 @@ func watchTicks(t *testing.T, pm *fluxmonitorv2.PollManager, waitDuration time.D } func TestPollManager_PollTicker(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: pollTickerDefaultDuration, PollTickerDisabled: false, @@ -104,6 +105,7 @@ func TestPollManager_PollTicker(t *testing.T) { } func TestPollManager_IdleTimer(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: 100 * time.Millisecond, PollTickerDisabled: true, @@ -126,6 +128,7 @@ func TestPollManager_IdleTimer(t *testing.T) { } func TestPollManager_RoundTimer(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: pollTickerDefaultDuration, PollTickerDisabled: true, @@ -149,6 +152,7 @@ func TestPollManager_RoundTimer(t *testing.T) { } func TestPollManager_RetryTimer(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: pollTickerDefaultDuration, PollTickerDisabled: true, @@ -185,6 +189,7 @@ func TestPollManager_RetryTimer(t *testing.T) { } func TestPollManager_InitialPoll(t *testing.T) { + t.Parallel() pm := newPollManager(t) pm.Start(false, flux_aggregator_wrapper.OracleRoundState{}) @@ -193,6 +198,7 @@ func TestPollManager_InitialPoll(t *testing.T) { } func TestPollManager_HibernationTimer(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: pollTickerDefaultDuration, PollTickerDisabled: true, @@ -214,6 +220,7 @@ func TestPollManager_HibernationTimer(t *testing.T) { } func TestPollManager_HibernationOnStartThenAwaken(t *testing.T) { + t.Parallel() pm, err := fluxmonitorv2.NewPollManager(fluxmonitorv2.PollManagerConfig{ PollTickerInterval: pollTickerDefaultDuration, PollTickerDisabled: false, @@ -248,6 +255,7 @@ func TestPollManager_HibernationOnStartThenAwaken(t *testing.T) { } func TestPollManager_AwakeOnStartThenHibernate(t *testing.T) { + t.Parallel() pm := newPollManager(t) pm.Start(false, flux_aggregator_wrapper.OracleRoundState{ @@ -272,6 +280,7 @@ func TestPollManager_AwakeOnStartThenHibernate(t *testing.T) { } func TestPollManager_ShouldPerformInitialPoll(t *testing.T) { + t.Parallel() testCases := []struct { name string pollTickerDisabled bool @@ -339,6 +348,7 @@ func TestPollManager_ShouldPerformInitialPoll(t *testing.T) { } func TestPollManager_Stop(t *testing.T) { + t.Parallel() pm := newPollManager(t) pm.Start(false, flux_aggregator_wrapper.OracleRoundState{ @@ -362,6 +372,7 @@ func TestPollManager_Stop(t *testing.T) { } func TestPollManager_ResetIdleTimer(t *testing.T) { + t.Parallel() pm := newPollManager(t) // Start again in awake mode @@ -382,6 +393,7 @@ func TestPollManager_ResetIdleTimer(t *testing.T) { } func TestPollManager_ResetIdleTimerWhenHibernating(t *testing.T) { + t.Parallel() pm := newPollManager(t) // Start in hibernation @@ -402,6 +414,7 @@ func TestPollManager_ResetIdleTimerWhenHibernating(t *testing.T) { } func TestPollManager_Reset(t *testing.T) { + t.Parallel() pm := newPollManager(t) // Start again in awake mode @@ -429,6 +442,7 @@ func TestPollManager_Reset(t *testing.T) { } func TestPollManager_ResetWhenHibernating(t *testing.T) { + t.Parallel() pm := newPollManager(t) // Start in hibernation diff --git a/core/services/fluxmonitorv2/submission_checker_test.go b/core/services/fluxmonitorv2/submission_checker_test.go index f8c63fef4bd..ae543c772a5 100644 --- a/core/services/fluxmonitorv2/submission_checker_test.go +++ b/core/services/fluxmonitorv2/submission_checker_test.go @@ -11,6 +11,7 @@ import ( ) func TestSubmissionChecker_IsValid(t *testing.T) { + t.Parallel() testCases := []struct { name string answer decimal.Decimal diff --git a/core/services/fluxmonitorv2/validate_test.go b/core/services/fluxmonitorv2/validate_test.go index 40efd1d724d..81d9215bea8 100644 --- a/core/services/fluxmonitorv2/validate_test.go +++ b/core/services/fluxmonitorv2/validate_test.go @@ -21,6 +21,7 @@ func (testcfg) DefaultHTTPTimeout() commonconfig.Duration { } func TestValidate(t *testing.T) { + t.Parallel() var tt = []struct { name string toml string diff --git a/core/services/gateway/handlers/functions/subscriptions/orm_test.go b/core/services/gateway/handlers/functions/subscriptions/orm_test.go index f75ab0b98c1..e2d7cfe9f49 100644 --- a/core/services/gateway/handlers/functions/subscriptions/orm_test.go +++ b/core/services/gateway/handlers/functions/subscriptions/orm_test.go @@ -237,6 +237,7 @@ func TestORM_UpsertSubscription(t *testing.T) { }) } func Test_NewORM(t *testing.T) { + t.Parallel() t.Run("OK-create_ORM", func(t *testing.T) { _, err := subscriptions.NewORM(pgtest.NewSqlxDB(t), logger.TestLogger(t), testutils.NewAddress()) require.NoError(t, err) diff --git a/core/services/gateway/handlers/functions/subscriptions/subscriptions_test.go b/core/services/gateway/handlers/functions/subscriptions/subscriptions_test.go index 212029b73f7..04a5d14102f 100644 --- a/core/services/gateway/handlers/functions/subscriptions/subscriptions_test.go +++ b/core/services/gateway/handlers/functions/subscriptions/subscriptions_test.go @@ -29,6 +29,7 @@ const ( ) func TestSubscriptions_OnePass(t *testing.T) { + t.Parallel() getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000003") getSubscriptionsInRange := hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000109e6e1b12098cc8f3a1e9719a817ec53ab9b35c000000000000000000000000000000000000000000000000000034e23f515cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5340f0968ee8b7dfd97e3327a6139273cc2c4fa000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc14b92364c75e20000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005439e5881a529f3ccbffc0e82d49f9db3950aefe") @@ -72,6 +73,7 @@ func TestSubscriptions_OnePass(t *testing.T) { } func TestSubscriptions_MultiPass(t *testing.T) { + t.Parallel() const ncycles int32 = 5 var currentCycle atomic.Int32 getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000006") @@ -119,6 +121,7 @@ func TestSubscriptions_MultiPass(t *testing.T) { } func TestSubscriptions_Stored(t *testing.T) { + t.Parallel() getSubscriptionCount := hexutil.MustDecode("0x0000000000000000000000000000000000000000000000000000000000000003") getSubscriptionsInRange := hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000240000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000109e6e1b12098cc8f3a1e9719a817ec53ab9b35c000000000000000000000000000000000000000000000000000034e23f515cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000f5340f0968ee8b7dfd97e3327a6139273cc2c4fa000000000000000000000000000000000000000000000001158e460913d000000000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001bc14b92364c75e20000000000000000000000009ed925d8206a4f88a2f643b28b3035b315753cd60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000005439e5881a529f3ccbffc0e82d49f9db3950aefe") diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go index d8678844d25..02136583e49 100644 --- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go +++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go @@ -36,6 +36,7 @@ answer; ` func TestAdapter_Integration(t *testing.T) { + testutils.SkipShortDB(t) logger := logger.TestLogger(t) cfg := configtest.NewTestGeneralConfig(t) url := cfg.Database().URL() diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go index c7fd7982904..8fc55abc7e7 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v02/v02_request_test.go @@ -101,6 +101,7 @@ func setupClient(t *testing.T) *client { } func TestV02_SingleFeedRequest(t *testing.T) { + t.Parallel() upkeepId := big.NewInt(123456789) tests := []struct { name string @@ -382,6 +383,7 @@ func TestV02_SingleFeedRequest(t *testing.T) { } func TestV02_DoMercuryRequestV02(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" tests := []struct { @@ -624,6 +626,7 @@ func TestV02_DoMercuryRequestV02(t *testing.T) { } func TestV02_DoMercuryRequestV02_MultipleFeedsSuccess(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -665,6 +668,7 @@ func TestV02_DoMercuryRequestV02_MultipleFeedsSuccess(t *testing.T) { } func TestV02_DoMercuryRequestV02_Timeout(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -719,6 +723,7 @@ func TestV02_DoMercuryRequestV02_Timeout(t *testing.T) { } func TestV02_DoMercuryRequestV02_OneFeedSuccessOneFeedPipelineError(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -766,6 +771,7 @@ func TestV02_DoMercuryRequestV02_OneFeedSuccessOneFeedPipelineError(t *testing.T } func TestV02_DoMercuryRequestV02_OneFeedSuccessOneFeedErrCode(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -813,6 +819,7 @@ func TestV02_DoMercuryRequestV02_OneFeedSuccessOneFeedErrCode(t *testing.T) { } func TestV02_DoMercuryRequestV02_OneFeedSuccessOneFeedPipelineErrorConvertedError(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go index 9c0e2aaa147..be99296d153 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/mercury/v03/v03_request_test.go @@ -99,6 +99,7 @@ func setupClient(t *testing.T) *client { } func TestV03_DoMercuryRequestV03(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) tests := []struct { @@ -179,6 +180,7 @@ func TestV03_DoMercuryRequestV03(t *testing.T) { } func TestV03_DoMercuryRequestV03_MultipleFeedsSuccess(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -230,6 +232,7 @@ func TestV03_DoMercuryRequestV03_MultipleFeedsSuccess(t *testing.T) { } func TestV03_DoMercuryRequestV03_Timeout(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -286,6 +289,7 @@ func TestV03_DoMercuryRequestV03_Timeout(t *testing.T) { } func TestV03_DoMercuryRequestV03_OneFeedSuccessOneFeedPipelineError(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -342,6 +346,7 @@ func TestV03_DoMercuryRequestV03_OneFeedSuccessOneFeedPipelineError(t *testing.T } func TestV03_DoMercuryRequestV03_OneFeedSuccessOneFeedErrCode(t *testing.T) { + t.Parallel() upkeepId, _ := new(big.Int).SetString("88786950015966611018675766524283132478093844178961698330929478019253453382042", 10) pluginRetryKey := "88786950015966611018675766524283132478093844178961698330929478019253453382042|34" @@ -412,6 +417,7 @@ func TestV03_DoMercuryRequestV03_OneFeedSuccessOneFeedErrCode(t *testing.T) { } func TestV03_MultiFeedRequest(t *testing.T) { + t.Parallel() upkeepId := big.NewInt(123456789) tests := []struct { name string diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index 7632bbb7a27..edb924f9874 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -116,6 +116,7 @@ func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capab } func TestEngineWithHardcodedWorkflow(t *testing.T) { + t.Parallel() ctx := testutils.Context(t) reg := coreCap.NewRegistry(logger.TestLogger(t)) @@ -288,6 +289,7 @@ func mockTarget() *mockCapability { } func TestEngine_ErrorsTheWorkflowIfAStepErrors(t *testing.T) { + t.Parallel() ctx := testutils.Context(t) reg := coreCap.NewRegistry(logger.TestLogger(t)) @@ -388,6 +390,7 @@ func mockAction() (*mockCapability, values.Value) { } func TestEngine_MultiStepDependencies(t *testing.T) { + t.Parallel() ctx := testutils.Context(t) reg := coreCap.NewRegistry(logger.TestLogger(t)) diff --git a/core/services/workflows/models_test.go b/core/services/workflows/models_test.go index 61aced2ed19..232e91eaaa8 100644 --- a/core/services/workflows/models_test.go +++ b/core/services/workflows/models_test.go @@ -8,6 +8,7 @@ import ( ) func TestParse_Graph(t *testing.T) { + t.Parallel() testCases := []struct { name string yaml string diff --git a/core/services/workflows/models_yaml_test.go b/core/services/workflows/models_yaml_test.go index 411781a3782..2732f1b44c7 100644 --- a/core/services/workflows/models_yaml_test.go +++ b/core/services/workflows/models_yaml_test.go @@ -52,6 +52,7 @@ var transformJSON = cmp.FilterValues(func(x, y []byte) bool { })) func TestWorkflowSpecMarshalling(t *testing.T) { + t.Parallel() fixtureReader := yamlFixtureReaderBytes(t, "marshalling") t.Run("Type coercion", func(t *testing.T) { @@ -168,6 +169,7 @@ func TestWorkflowSpecMarshalling(t *testing.T) { } func TestJsonSchema(t *testing.T) { + t.Parallel() t.Run("GenerateJsonSchema", func(t *testing.T) { expectedSchemaPath := fixtureDir + "workflow_schema.json" generatedSchema, err := GenerateJsonSchema() diff --git a/core/services/workflows/state_test.go b/core/services/workflows/state_test.go index 9e69520c242..0917662ccb6 100644 --- a/core/services/workflows/state_test.go +++ b/core/services/workflows/state_test.go @@ -11,6 +11,7 @@ import ( ) func TestInterpolateKey(t *testing.T) { + t.Parallel() val, err := values.NewMap( map[string]any{ "reports": map[string]any{ @@ -202,6 +203,7 @@ func TestInterpolateKey(t *testing.T) { } func TestInterpolateInputsFromState(t *testing.T) { + t.Parallel() testCases := []struct { name string inputs map[string]any diff --git a/main_test.go b/main_test.go index 51707f0d9fb..81e056e3b84 100644 --- a/main_test.go +++ b/main_test.go @@ -43,6 +43,9 @@ func TestMain(m *testing.M) { } func TestScripts(t *testing.T) { + if testing.Short() { + t.Skip("skipping testscript") + } t.Parallel() visitor := txtar.NewDirVisitor("testdata/scripts", txtar.Recurse, func(path string) error { From 5b33a3296f895cec8a23ba2e235989868f398ddb Mon Sep 17 00:00:00 2001 From: Lei Date: Thu, 18 Apr 2024 13:06:02 -0700 Subject: [PATCH 10/26] support decimals (#12812) * support decimals * address comments * use IERC20Metadata --- .changeset/loud-peaches-beg.md | 5 + contracts/.changeset/heavy-horses-greet.md | 5 + .../v2_3/IAutomationRegistryMaster2_3.sol | 3 +- .../dev/interfaces/v2_3/IWrappedNative.sol | 2 +- .../dev/test/AutomationRegistrar2_3.t.sol | 20 +- .../dev/test/AutomationRegistry2_3.t.sol | 295 +++++++++++------- .../v0.8/automation/dev/test/BaseTest.t.sol | 60 ++-- .../dev/v2_3/AutomationRegistrar2_3.sol | 2 +- .../dev/v2_3/AutomationRegistry2_3.sol | 2 +- .../dev/v2_3/AutomationRegistryBase2_3.sol | 40 ++- .../dev/v2_3/AutomationRegistryLogicA2_3.sol | 2 +- .../dev/v2_3/AutomationRegistryLogicB2_3.sol | 2 +- .../dev/v2_3/AutomationRegistryLogicC2_3.sol | 2 +- .../automation/mocks/ERC20Mock6Decimals.sol | 17 + .../automation/AutomationRegistrar2_3.test.ts | 1 + .../automation/AutomationRegistry2_3.test.ts | 8 + .../automation_registrar_wrapper2_3.go | 2 +- ...automation_registry_logic_a_wrapper_2_3.go | 5 +- ...automation_registry_logic_b_wrapper_2_3.go | 7 +- .../automation_registry_wrapper_2_3.go | 7 +- ..._automation_registry_master_wrapper_2_3.go | 5 +- ...rapper-dependency-versions-do-not-edit.txt | 10 +- 22 files changed, 335 insertions(+), 167 deletions(-) create mode 100644 .changeset/loud-peaches-beg.md create mode 100644 contracts/.changeset/heavy-horses-greet.md create mode 100644 contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol diff --git a/.changeset/loud-peaches-beg.md b/.changeset/loud-peaches-beg.md new file mode 100644 index 00000000000..cd880ae5f5c --- /dev/null +++ b/.changeset/loud-peaches-beg.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +support decimals #added diff --git a/contracts/.changeset/heavy-horses-greet.md b/contracts/.changeset/heavy-horses-greet.md new file mode 100644 index 00000000000..51912232c26 --- /dev/null +++ b/contracts/.changeset/heavy-horses-greet.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +support decimals #added diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol index 66761737e8f..90fdd82bfe7 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IAutomationRegistryMaster2_3.sol @@ -306,6 +306,7 @@ interface AutomationRegistryBase2_3 { uint32 gasFeePPB; uint24 flatFeeMilliCents; address priceFeed; + uint8 decimals; uint256 fallbackPrice; uint96 minSpend; } @@ -404,5 +405,5 @@ interface IAutomationV21PlusCommon { // THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON: /* -[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] +[{"inputs":[{"internalType":"contract AutomationRegistryLogicA2_3","name":"logicA","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ArrayHasNoEntries","type":"error"},{"inputs":[],"name":"CannotCancel","type":"error"},{"inputs":[],"name":"CheckDataExceedsLimit","type":"error"},{"inputs":[],"name":"ConfigDigestMismatch","type":"error"},{"inputs":[],"name":"DuplicateEntry","type":"error"},{"inputs":[],"name":"DuplicateSigners","type":"error"},{"inputs":[],"name":"GasLimitCanOnlyIncrease","type":"error"},{"inputs":[],"name":"GasLimitOutsideRange","type":"error"},{"inputs":[],"name":"IncorrectNumberOfFaultyOracles","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSignatures","type":"error"},{"inputs":[],"name":"IncorrectNumberOfSigners","type":"error"},{"inputs":[],"name":"IndexOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"available","type":"uint256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InsufficientLinkLiquidity","type":"error"},{"inputs":[],"name":"InvalidDataLength","type":"error"},{"inputs":[],"name":"InvalidFeed","type":"error"},{"inputs":[],"name":"InvalidPayee","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidReport","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"InvalidTransmitter","type":"error"},{"inputs":[],"name":"InvalidTrigger","type":"error"},{"inputs":[],"name":"InvalidTriggerType","type":"error"},{"inputs":[],"name":"MigrationNotPermitted","type":"error"},{"inputs":[],"name":"MustSettleOffchain","type":"error"},{"inputs":[],"name":"MustSettleOnchain","type":"error"},{"inputs":[],"name":"NotAContract","type":"error"},{"inputs":[],"name":"OnlyActiveSigners","type":"error"},{"inputs":[],"name":"OnlyActiveTransmitters","type":"error"},{"inputs":[],"name":"OnlyCallableByAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByLINKToken","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByOwnerOrRegistrar","type":"error"},{"inputs":[],"name":"OnlyCallableByPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedAdmin","type":"error"},{"inputs":[],"name":"OnlyCallableByProposedPayee","type":"error"},{"inputs":[],"name":"OnlyCallableByUpkeepPrivilegeManager","type":"error"},{"inputs":[],"name":"OnlyFinanceAdmin","type":"error"},{"inputs":[],"name":"OnlyPausedUpkeep","type":"error"},{"inputs":[],"name":"OnlySimulatedBackend","type":"error"},{"inputs":[],"name":"OnlyUnpausedUpkeep","type":"error"},{"inputs":[],"name":"ParameterLengthError","type":"error"},{"inputs":[],"name":"ReentrantCall","type":"error"},{"inputs":[],"name":"RegistryPaused","type":"error"},{"inputs":[],"name":"RepeatedSigner","type":"error"},{"inputs":[],"name":"RepeatedTransmitter","type":"error"},{"inputs":[{"internalType":"bytes","name":"reason","type":"bytes"}],"name":"TargetCheckReverted","type":"error"},{"inputs":[],"name":"TooManyOracles","type":"error"},{"inputs":[],"name":"TranscoderNotSet","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UpkeepAlreadyExists","type":"error"},{"inputs":[],"name":"UpkeepCancelled","type":"error"},{"inputs":[],"name":"UpkeepNotCanceled","type":"error"},{"inputs":[],"name":"UpkeepNotNeeded","type":"error"},{"inputs":[],"name":"ValueNotChanged","type":"error"},{"inputs":[],"name":"ZeroAddressNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"AdminPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"overrides","type":"tuple"}],"name":"BillingConfigOverridden","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"BillingConfigOverrideRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20Metadata","name":"token","type":"address"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"indexed":false,"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"config","type":"tuple"}],"name":"BillingConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"CancelledUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newModule","type":"address"}],"name":"ChainSpecificModuleUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"previousConfigBlockNumber","type":"uint32"},{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"configCount","type":"uint64"},{"indexed":false,"internalType":"address[]","name":"signers","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"uint8","name":"f","type":"uint8"},{"indexed":false,"internalType":"bytes","name":"onchainConfig","type":"bytes"},{"indexed":false,"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"ConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"DedupKeyAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAddress","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint96","name":"amount","type":"uint96"}],"name":"FundsAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"FundsWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"InsufficientFundsUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"payments","type":"uint256[]"}],"name":"NOPsSettledOffchain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"transmitters","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"payees","type":"address[]"}],"name":"PayeesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"PayeeshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"transmitter","type":"address"},{"indexed":true,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"payee","type":"address"}],"name":"PaymentWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"ReorgedUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"StaleUpkeepReport","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"Transmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"UpkeepAdminTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"uint64","name":"atBlockHeight","type":"uint64"}],"name":"UpkeepCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"UpkeepCheckDataSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint96","name":"gasLimit","type":"uint96"}],"name":"UpkeepGasLimitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"remainingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"destination","type":"address"}],"name":"UpkeepMigrated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"UpkeepOffchainConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint96","name":"totalPayment","type":"uint96"},{"indexed":false,"internalType":"uint256","name":"gasUsed","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"gasOverhead","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"trigger","type":"bytes"}],"name":"UpkeepPerformed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"privilegeConfig","type":"bytes"}],"name":"UpkeepPrivilegeConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"startingBalance","type":"uint256"},{"indexed":false,"internalType":"address","name":"importedFrom","type":"address"}],"name":"UpkeepReceived","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"uint32","name":"performGas","type":"uint32"},{"indexed":false,"internalType":"address","name":"admin","type":"address"}],"name":"UpkeepRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"UpkeepTriggerConfigSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"UpkeepUnpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fallbackTo","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDetails","outputs":[{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfigDigestAndEpoch","outputs":[{"internalType":"bool","name":"scanLogs","type":"bool"},{"internalType":"bytes32","name":"configDigest","type":"bytes32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onTokenTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bytes","name":"onchainConfigBytes","type":"bytes"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"setConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"},{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"onchainConfig","type":"tuple"},{"internalType":"uint64","name":"offchainConfigVersion","type":"uint64"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"},{"internalType":"contract IERC20Metadata[]","name":"billingTokens","type":"address[]"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig[]","name":"billingConfigs","type":"tuple[]"}],"name":"setConfigTypeSafe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[3]","name":"reportContext","type":"bytes32[3]"},{"internalType":"bytes","name":"rawReport","type":"bytes"},{"internalType":"bytes32[]","name":"rs","type":"bytes32[]"},{"internalType":"bytes32[]","name":"ss","type":"bytes32[]"},{"internalType":"bytes32","name":"rawVs","type":"bytes32"}],"name":"transmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"typeAndVersion","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicB2_3","name":"logicB","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"cancelUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"},{"internalType":"address","name":"destination","type":"address"}],"name":"migrateUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"encodedUpkeeps","type":"bytes"}],"name":"receiveUpkeeps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"name":"registerUpkeep","outputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AutomationRegistryLogicC2_3","name":"logicC","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"acceptUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint96","name":"amount","type":"uint96"}],"name":"addFunds","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes[]","name":"values","type":"bytes[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"checkCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerData","type":"bytes"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"checkUpkeep","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"uint256","name":"fastGasWei","type":"uint256"},{"internalType":"uint256","name":"linkUSD","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeCallback","outputs":[{"internalType":"bool","name":"upkeepNeeded","type":"bool"},{"internalType":"bytes","name":"performData","type":"bytes"},{"internalType":"enum AutomationRegistryBase2_3.UpkeepFailureReason","name":"upkeepFailureReason","type":"uint8"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"pauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"removeBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"}],"internalType":"struct AutomationRegistryBase2_3.BillingOverrides","name":"billingOverrides","type":"tuple"}],"name":"setBillingOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"newCheckData","type":"bytes"}],"name":"setUpkeepCheckData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint32","name":"gasLimit","type":"uint32"}],"name":"setUpkeepGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"config","type":"bytes"}],"name":"setUpkeepOffchainConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"triggerConfig","type":"bytes"}],"name":"setUpkeepTriggerConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"simulatePerformUpkeep","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUsed","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferUpkeepAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"unpauseUpkeep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"asset","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawERC20Fees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawLink","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"link","type":"address"},{"internalType":"address","name":"linkUSDFeed","type":"address"},{"internalType":"address","name":"nativeUSDFeed","type":"address"},{"internalType":"address","name":"fastGasFeed","type":"address"},{"internalType":"address","name":"automationForwarderLogic","type":"address"},{"internalType":"address","name":"allowedReadOnlyAddress","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"payoutMode","type":"uint8"},{"internalType":"address","name":"wrappedNativeTokenAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"}],"name":"acceptPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableOffchainPayments","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"maxCount","type":"uint256"}],"name":"getActiveUpkeepIDs","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"}],"name":"getAdminPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllowedReadOnlyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAutomationForwarderLogic","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getBalance","outputs":[{"internalType":"uint96","name":"balance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getBillingToken","outputs":[{"internalType":"contract IERC20Metadata","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"getBillingTokenConfig","outputs":[{"components":[{"internalType":"uint32","name":"gasFeePPB","type":"uint32"},{"internalType":"uint24","name":"flatFeeMilliCents","type":"uint24"},{"internalType":"contract AggregatorV3Interface","name":"priceFeed","type":"address"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"fallbackPrice","type":"uint256"},{"internalType":"uint96","name":"minSpend","type":"uint96"}],"internalType":"struct AutomationRegistryBase2_3.BillingConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBillingTokens","outputs":[{"internalType":"contract IERC20Metadata[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCancellationDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getChainModule","outputs":[{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConditionalGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"components":[{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackNativePrice","type":"uint256"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.OnchainConfig","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFallbackNativePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFastGasFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepID","type":"uint256"}],"name":"getForwarder","outputs":[{"internalType":"contract IAutomationForwarder","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHotVars","outputs":[{"components":[{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint8","name":"f","type":"uint8"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bool","name":"reentrancyGuard","type":"bool"},{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"},{"internalType":"contract IChainModule","name":"chainModule","type":"address"}],"internalType":"struct AutomationRegistryBase2_3.HotVars","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLinkUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLogGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"triggerType","type":"uint8"},{"internalType":"uint32","name":"gasLimit","type":"uint32"},{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getMaxPaymentForGas","outputs":[{"internalType":"uint96","name":"maxPayment","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalance","outputs":[{"internalType":"uint96","name":"","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getMinBalanceForUpkeep","outputs":[{"internalType":"uint96","name":"minBalance","type":"uint96"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNativeUSDFeedAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumUpkeeps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPayoutMode","outputs":[{"internalType":"enum AutomationRegistryBase2_3.PayoutMode","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"}],"name":"getPeerRegistryMigrationPermission","outputs":[{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPerPerformByteGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getPerSignerGasOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getReorgProtectionEnabled","outputs":[{"internalType":"bool","name":"reorgProtectionEnabled","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"billingToken","type":"address"}],"name":"getReserveAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getSignerInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"components":[{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"uint96","name":"ownerLinkBalance","type":"uint96"},{"internalType":"uint256","name":"expectedLinkBalance","type":"uint256"},{"internalType":"uint96","name":"totalPremium","type":"uint96"},{"internalType":"uint256","name":"numUpkeeps","type":"uint256"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"bytes32","name":"latestConfigDigest","type":"bytes32"},{"internalType":"uint32","name":"latestEpoch","type":"uint32"},{"internalType":"bool","name":"paused","type":"bool"}],"internalType":"struct IAutomationV21PlusCommon.StateLegacy","name":"state","type":"tuple"},{"components":[{"internalType":"uint32","name":"paymentPremiumPPB","type":"uint32"},{"internalType":"uint32","name":"flatFeeMicroLink","type":"uint32"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint24","name":"stalenessSeconds","type":"uint24"},{"internalType":"uint16","name":"gasCeilingMultiplier","type":"uint16"},{"internalType":"uint96","name":"minUpkeepSpend","type":"uint96"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"},{"internalType":"uint256","name":"fallbackGasPrice","type":"uint256"},{"internalType":"uint256","name":"fallbackLinkPrice","type":"uint256"},{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"address[]","name":"registrars","type":"address[]"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"}],"internalType":"struct IAutomationV21PlusCommon.OnchainConfigLegacy","name":"config","type":"tuple"},{"internalType":"address[]","name":"signers","type":"address[]"},{"internalType":"address[]","name":"transmitters","type":"address[]"},{"internalType":"uint8","name":"f","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStorage","outputs":[{"components":[{"internalType":"address","name":"transcoder","type":"address"},{"internalType":"uint32","name":"checkGasLimit","type":"uint32"},{"internalType":"uint32","name":"maxPerformGas","type":"uint32"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"address","name":"upkeepPrivilegeManager","type":"address"},{"internalType":"uint32","name":"configCount","type":"uint32"},{"internalType":"uint32","name":"latestConfigBlockNumber","type":"uint32"},{"internalType":"uint32","name":"maxCheckDataSize","type":"uint32"},{"internalType":"address","name":"financeAdmin","type":"address"},{"internalType":"uint32","name":"maxPerformDataSize","type":"uint32"},{"internalType":"uint32","name":"maxRevertDataSize","type":"uint32"}],"internalType":"struct AutomationRegistryBase2_3.Storage","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTransmitCalldataFixedBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getTransmitCalldataPerSignerBytesOverhead","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"query","type":"address"}],"name":"getTransmitterInfo","outputs":[{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint8","name":"index","type":"uint8"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"uint96","name":"lastCollected","type":"uint96"},{"internalType":"address","name":"payee","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getTriggerType","outputs":[{"internalType":"enum AutomationRegistryBase2_3.Trigger","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getUpkeep","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint32","name":"performGas","type":"uint32"},{"internalType":"bytes","name":"checkData","type":"bytes"},{"internalType":"uint96","name":"balance","type":"uint96"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint64","name":"maxValidBlocknumber","type":"uint64"},{"internalType":"uint32","name":"lastPerformedBlockNumber","type":"uint32"},{"internalType":"uint96","name":"amountSpent","type":"uint96"},{"internalType":"bool","name":"paused","type":"bool"},{"internalType":"bytes","name":"offchainConfig","type":"bytes"}],"internalType":"struct IAutomationV21PlusCommon.UpkeepInfoLegacy","name":"upkeepInfo","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepPrivilegeConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"}],"name":"getUpkeepTriggerConfig","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrappedNativeTokenAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"dedupKey","type":"bytes32"}],"name":"hasDedupKey","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setAdminPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"payees","type":"address[]"}],"name":"setPayees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"peer","type":"address"},{"internalType":"enum AutomationRegistryBase2_3.MigrationPermission","name":"permission","type":"uint8"}],"name":"setPeerRegistryMigrationPermission","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"upkeepId","type":"uint256"},{"internalType":"bytes","name":"newPrivilegeConfig","type":"bytes"}],"name":"setUpkeepPrivilegeConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"settleNOPsOffchain","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20Metadata","name":"token","type":"address"}],"name":"supportsBillingToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"transmitter","type":"address"},{"internalType":"address","name":"proposed","type":"address"}],"name":"transferPayeeship","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"upkeepVersion","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawPayment","outputs":[],"stateMutability":"nonpayable","type":"function"}] */ diff --git a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol index 5b03b2efeb1..dd371033023 100644 --- a/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol +++ b/contracts/src/v0.8/automation/dev/interfaces/v2_3/IWrappedNative.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; interface IWrappedNative is IERC20 { function deposit() external payable; diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol index e840d8b7397..76b808d1f05 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistrar2_3.t.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {BaseTest} from "./BaseTest.t.sol"; import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; import {AutomationRegistrar2_3} from "../v2_3/AutomationRegistrar2_3.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryBase2_3.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; @@ -51,8 +51,8 @@ contract RegisterUpkeep is SetUp { function testUSDToken_autoApproveOff_happy() external { vm.startPrank(UPKEEP_ADMIN); - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken)); - usdToken.approve(address(registrar), amount); + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); registrar.registerUpkeep( AutomationRegistrar2_3.RegistrationParams({ @@ -61,7 +61,7 @@ contract RegisterUpkeep is SetUp { adminAddress: UPKEEP_ADMIN, gasLimit: 10_000, triggerType: 0, - billingToken: usdToken, + billingToken: usdToken18, name: "foobar", encryptedEmail: "", checkData: bytes("check data"), @@ -70,7 +70,7 @@ contract RegisterUpkeep is SetUp { }) ); - assertEq(usdToken.balanceOf(address(registrar)), amount); + assertEq(usdToken18.balanceOf(address(registrar)), amount); assertEq(registry.getNumUpkeeps(), 0); } @@ -106,8 +106,8 @@ contract RegisterUpkeep is SetUp { registrar.setTriggerConfig(0, AutomationRegistrar2_3.AutoApproveType.ENABLED_ALL, 1000); vm.startPrank(UPKEEP_ADMIN); - uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken)); - usdToken.approve(address(registrar), amount); + uint96 amount = uint96(registrar.getMinimumRegistrationAmount(usdToken18)); + usdToken18.approve(address(registrar), amount); registrar.registerUpkeep( AutomationRegistrar2_3.RegistrationParams({ @@ -116,7 +116,7 @@ contract RegisterUpkeep is SetUp { adminAddress: UPKEEP_ADMIN, gasLimit: 10_000, triggerType: 0, - billingToken: usdToken, + billingToken: usdToken18, name: "foobar", encryptedEmail: "", checkData: bytes("check data"), @@ -125,8 +125,8 @@ contract RegisterUpkeep is SetUp { }) ); - assertEq(usdToken.balanceOf(address(registrar)), 0); - assertEq(usdToken.balanceOf(address(registry)), amount); + assertEq(usdToken18.balanceOf(address(registrar)), 0); + assertEq(usdToken18.balanceOf(address(registry)), amount); assertEq(registry.getNumUpkeeps(), 1); } diff --git a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index ef58dbbe4be..4d2cfbbec36 100644 --- a/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol +++ b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -7,7 +7,7 @@ import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryB import {AutomationRegistrar2_3 as Registrar} from "../v2_3/AutomationRegistrar2_3.sol"; import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; // forge test --match-path src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol @@ -23,27 +23,30 @@ contract SetUp is BaseTest { bytes internal constant offchainConfigBytes = abi.encode(1234, ZERO_ADDRESS); uint256 linkUpkeepID; - uint256 linkUpkeepID2; - uint256 usdUpkeepID; + uint256 linkUpkeepID2; // 2 upkeeps use the same billing token (LINK) to test migration scenario + uint256 usdUpkeepID18; // 1 upkeep uses ERC20 token with 18 decimals + uint256 usdUpkeepID6; // 1 upkeep uses ERC20 token with 6 decimals uint256 nativeUpkeepID; function setUp() public virtual override { super.setUp(); - (registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); config = registry.getConfig(); vm.startPrank(OWNER); linkToken.approve(address(registry), type(uint256).max); - usdToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); weth.approve(address(registry), type(uint256).max); vm.startPrank(UPKEEP_ADMIN); linkToken.approve(address(registry), type(uint256).max); - usdToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); weth.approve(address(registry), type(uint256).max); vm.startPrank(STRANGER); linkToken.approve(address(registry), type(uint256).max); - usdToken.approve(address(registry), type(uint256).max); + usdToken6.approve(address(registry), type(uint256).max); + usdToken18.approve(address(registry), type(uint256).max); weth.approve(address(registry), type(uint256).max); vm.stopPrank(); @@ -69,12 +72,23 @@ contract SetUp is BaseTest { "" ); - usdUpkeepID = registry.registerUpkeep( + usdUpkeepID18 = registry.registerUpkeep( address(TARGET1), config.maxPerformGas, UPKEEP_ADMIN, uint8(Trigger.CONDITION), - address(usdToken), + address(usdToken18), + "", + "", + "" + ); + + usdUpkeepID6 = registry.registerUpkeep( + address(TARGET1), + config.maxPerformGas, + UPKEEP_ADMIN, + uint8(Trigger.CONDITION), + address(usdToken6), "", "", "" @@ -94,7 +108,8 @@ contract SetUp is BaseTest { vm.startPrank(OWNER); registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); registry.addFunds(linkUpkeepID2, registry.getMinBalanceForUpkeep(linkUpkeepID2)); - registry.addFunds(usdUpkeepID, registry.getMinBalanceForUpkeep(usdUpkeepID)); + registry.addFunds(usdUpkeepID18, registry.getMinBalanceForUpkeep(usdUpkeepID18)); + registry.addFunds(usdUpkeepID6, registry.getMinBalanceForUpkeep(usdUpkeepID6)); registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); vm.stopPrank(); } @@ -174,21 +189,21 @@ contract AddFunds is SetUp { vm.startPrank(UPKEEP_ADMIN); uint256 startLINKRegistryBalance = linkToken.balanceOf(address(registry)); - uint256 startUSDRegistryBalance = usdToken.balanceOf(address(registry)); + uint256 startUSDRegistryBalance = usdToken18.balanceOf(address(registry)); uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); - uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID); + uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID18); registry.addFunds(linkUpkeepID, 1); assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID), startUSDRegistryBalance); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance); assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken.balanceOf(address(registry)), startUSDUpkeepBalance); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance); - registry.addFunds(usdUpkeepID, 2); + registry.addFunds(usdUpkeepID18, 2); assertEq(registry.getBalance(linkUpkeepID), startLinkUpkeepBalance + 1); - assertEq(registry.getBalance(usdUpkeepID), startUSDRegistryBalance + 2); + assertEq(registry.getBalance(usdUpkeepID18), startUSDRegistryBalance + 2); assertEq(linkToken.balanceOf(address(registry)), startLINKRegistryBalance + 1); - assertEq(usdToken.balanceOf(address(registry)), startUSDUpkeepBalance + 2); + assertEq(usdToken18.balanceOf(address(registry)), startUSDUpkeepBalance + 2); } function test_emitsAnEvent() public { @@ -258,10 +273,10 @@ contract Withdraw is SetUp { } function test_WithdrawERC20Fees_RespectsReserveAmount() public { - assertEq(registry.getBalance(usdUpkeepID), registry.getReserveAmount(address(usdToken))); + assertEq(registry.getBalance(usdUpkeepID18), registry.getReserveAmount(address(usdToken18))); vm.startPrank(FINANCE_ADMIN); vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawERC20Fees(address(usdToken), FINANCE_ADMIN, 1); + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); } function test_WithdrawERC20Fees_RevertsWhen_AttemptingToWithdrawLINK() public { @@ -273,35 +288,35 @@ contract Withdraw is SetUp { } function test_WithdrawERC20Fees_RevertsWhen_LinkAvailableForPaymentIsNegative() public { - _transmit(usdUpkeepID, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance + _transmit(usdUpkeepID18, registry); // adds USD token to finance withdrawable, and gives NOPs a LINK balance require(registry.linkAvailableForPayment() < 0, "linkAvailableForPayment should be negative"); vm.expectRevert(Registry.InsufficientLinkLiquidity.selector); vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken), FINANCE_ADMIN, 1); // should revert + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // should revert _mintLink(address(registry), uint256(registry.linkAvailableForPayment() * -10)); // top up LINK liquidity pool vm.prank(FINANCE_ADMIN); - registry.withdrawERC20Fees(address(usdToken), FINANCE_ADMIN, 1); // now finance can withdraw + registry.withdrawERC20Fees(address(usdToken18), FINANCE_ADMIN, 1); // now finance can withdraw } function testWithdrawERC20FeeSuccess() public { // deposit excess USDToken to the registry (this goes to the "finance withdrawable" pool be default) - uint256 startReserveAmount = registry.getReserveAmount(address(usdToken)); - uint256 startAmount = usdToken.balanceOf(address(registry)); - _mintERC20(address(registry), 1e10); + uint256 startReserveAmount = registry.getReserveAmount(address(usdToken18)); + uint256 startAmount = usdToken18.balanceOf(address(registry)); + _mintERC20_18Decimals(address(registry), 1e10); // depositing shouldn't change reserve amount - assertEq(registry.getReserveAmount(address(usdToken)), startReserveAmount); + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); vm.startPrank(FINANCE_ADMIN); // try to withdraw 1 USDToken - registry.withdrawERC20Fees(address(usdToken), aMockAddress, 1); + registry.withdrawERC20Fees(address(usdToken18), aMockAddress, 1); vm.stopPrank(); - assertEq(usdToken.balanceOf(address(aMockAddress)), 1); - assertEq(usdToken.balanceOf(address(registry)), startAmount + 1e10 - 1); - assertEq(registry.getReserveAmount(address(usdToken)), startReserveAmount); + assertEq(usdToken18.balanceOf(address(aMockAddress)), 1); + assertEq(usdToken18.balanceOf(address(registry)), startAmount + 1e10 - 1); + assertEq(registry.getReserveAmount(address(usdToken18)), startReserveAmount); } } @@ -343,7 +358,7 @@ contract SetConfig is SetUp { (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); assertEq(configCount, 1); - address billingTokenAddress = address(0x1111111111111111111111111111111111111111); + address billingTokenAddress = address(usdToken18); address[] memory billingTokens = new address[](1); billingTokens[0] = billingTokenAddress; @@ -351,9 +366,10 @@ contract SetConfig is SetUp { billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_000, flatFeeMilliCents: 20_000, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000 + minSpend: 100_000, + decimals: 18 }); bytes memory onchainConfigBytes = abi.encode(cfg); @@ -402,7 +418,7 @@ contract SetConfig is SetUp { AutomationRegistryBase2_3.BillingConfig memory config = registry.getBillingTokenConfig(billingTokenAddress); assertEq(config.gasFeePPB, 5_000); assertEq(config.flatFeeMilliCents, 20_000); - assertEq(config.priceFeed, 0x2222222222222222222222222222222222222222); + assertEq(config.priceFeed, address(USDTOKEN_USD_FEED)); assertEq(config.minSpend, 100_000); address[] memory tokens = registry.getBillingTokens(); @@ -413,8 +429,8 @@ contract SetConfig is SetUp { (uint32 configCount, , ) = registry.latestConfigDetails(); assertEq(configCount, 1); - address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111); - address billingTokenAddress2 = address(0x1111111111111111111111111111111111111112); + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(usdToken18); address[] memory billingTokens = new address[](2); billingTokens[0] = billingTokenAddress1; billingTokens[1] = billingTokenAddress2; @@ -423,16 +439,18 @@ contract SetConfig is SetUp { billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_001, flatFeeMilliCents: 20_001, - priceFeed: 0x2222222222222222222222222222222222222221, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 100, - minSpend: 100 + minSpend: 100, + decimals: 18 }); billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_002, flatFeeMilliCents: 20_002, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 200, - minSpend: 200 + minSpend: 200, + decimals: 18 }); bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); @@ -455,14 +473,14 @@ contract SetConfig is SetUp { AutomationRegistryBase2_3.BillingConfig memory config1 = registry.getBillingTokenConfig(billingTokenAddress1); assertEq(config1.gasFeePPB, 5_001); assertEq(config1.flatFeeMilliCents, 20_001); - assertEq(config1.priceFeed, 0x2222222222222222222222222222222222222221); + assertEq(config1.priceFeed, address(USDTOKEN_USD_FEED)); assertEq(config1.fallbackPrice, 100); assertEq(config1.minSpend, 100); AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); assertEq(config2.gasFeePPB, 5_002); assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, 0x2222222222222222222222222222222222222222); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); assertEq(config2.fallbackPrice, 200); assertEq(config2.minSpend, 200); @@ -475,7 +493,7 @@ contract SetConfig is SetUp { assertEq(configCount, 1); // BillingConfig1 - address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111); + address billingTokenAddress1 = address(usdToken18); address[] memory billingTokens1 = new address[](1); billingTokens1[0] = billingTokenAddress1; @@ -483,15 +501,16 @@ contract SetConfig is SetUp { billingConfigs1[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_001, flatFeeMilliCents: 20_001, - priceFeed: 0x2222222222222222222222222222222222222221, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 100, - minSpend: 100 + minSpend: 100, + decimals: 18 }); bytes memory onchainConfigBytesWithBilling1 = abi.encode(cfg, billingTokens1, billingConfigs1); // BillingConfig2 - address billingTokenAddress2 = address(0x1111111111111111111111111111111111111112); + address billingTokenAddress2 = address(usdToken18); address[] memory billingTokens2 = new address[](1); billingTokens2[0] = billingTokenAddress2; @@ -499,9 +518,10 @@ contract SetConfig is SetUp { billingConfigs2[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_002, flatFeeMilliCents: 20_002, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 200, - minSpend: 200 + minSpend: 200, + decimals: 18 }); bytes memory onchainConfigBytesWithBilling2 = abi.encode(cfg, billingTokens2, billingConfigs2); @@ -535,7 +555,7 @@ contract SetConfig is SetUp { AutomationRegistryBase2_3.BillingConfig memory config2 = registry.getBillingTokenConfig(billingTokenAddress2); assertEq(config2.gasFeePPB, 5_002); assertEq(config2.flatFeeMilliCents, 20_002); - assertEq(config2.priceFeed, 0x2222222222222222222222222222222222222222); + assertEq(config2.priceFeed, address(USDTOKEN_USD_FEED)); assertEq(config2.fallbackPrice, 200); assertEq(config2.minSpend, 200); @@ -547,8 +567,8 @@ contract SetConfig is SetUp { (uint32 configCount, , ) = registry.latestConfigDetails(); assertEq(configCount, 1); - address billingTokenAddress1 = address(0x1111111111111111111111111111111111111111); - address billingTokenAddress2 = address(0x1111111111111111111111111111111111111111); + address billingTokenAddress1 = address(linkToken); + address billingTokenAddress2 = address(linkToken); address[] memory billingTokens = new address[](2); billingTokens[0] = billingTokenAddress1; billingTokens[1] = billingTokenAddress2; @@ -557,16 +577,18 @@ contract SetConfig is SetUp { billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_001, flatFeeMilliCents: 20_001, - priceFeed: 0x2222222222222222222222222222222222222221, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 100, - minSpend: 100 + minSpend: 100, + decimals: 18 }); billingConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_002, flatFeeMilliCents: 20_002, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 200, - minSpend: 200 + minSpend: 200, + decimals: 18 }); bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); @@ -591,9 +613,10 @@ contract SetConfig is SetUp { billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_000, flatFeeMilliCents: 20_000, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000 + minSpend: 100_000, + decimals: 18 }); // deploy registry with OFF_CHAIN payout mode @@ -612,13 +635,40 @@ contract SetConfig is SetUp { ); } + function testSetConfigRevertDueToInvalidDecimals() public { + address[] memory billingTokens = new address[](1); + billingTokens[0] = address(linkToken); + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000, + decimals: 6 // link token should have 18 decimals + }); + + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + } + function testSetConfigWithNewTransmittersSuccess() public { registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); assertEq(configCount, 0); - address billingTokenAddress = address(0x1111111111111111111111111111111111111111); + address billingTokenAddress = address(usdToken18); address[] memory billingTokens = new address[](1); billingTokens[0] = billingTokenAddress; @@ -626,9 +676,10 @@ contract SetConfig is SetUp { billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: 5_000, flatFeeMilliCents: 20_000, - priceFeed: 0x2222222222222222222222222222222222222222, + priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 2_000_000_000, // $20 - minSpend: 100_000 + minSpend: 100_000, + decimals: 18 }); bytes memory onchainConfigBytes = abi.encode(cfg); @@ -790,10 +841,10 @@ contract NOPsSettlement is SetUp { (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken), "", "", ""); - _mintERC20(UPKEEP_ADMIN, 1e20); + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); vm.startPrank(UPKEEP_ADMIN); - usdToken.approve(address(registry), 1e20); + usdToken18.approve(address(registry), 1e20); registry.addFunds(id, 1e20); // manually create a transmit so transmitters earn some rewards @@ -831,10 +882,10 @@ contract NOPsSettlement is SetUp { (Registry registry, Registrar registrar) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken), "", "", ""); - _mintERC20(UPKEEP_ADMIN, 1e20); + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); vm.startPrank(UPKEEP_ADMIN); - usdToken.approve(address(registry), 1e20); + usdToken18.approve(address(registry), 1e20); registry.addFunds(id, 1e20); // manually create a transmit so TRANSMITTERS earn some rewards @@ -943,10 +994,10 @@ contract NOPsSettlement is SetUp { (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken), "", "", ""); - _mintERC20(UPKEEP_ADMIN, 1e20); + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); vm.startPrank(UPKEEP_ADMIN); - usdToken.approve(address(registry), 1e20); + usdToken18.approve(address(registry), 1e20); registry.addFunds(id, 1e20); // manually create a transmit so transmitters earn some rewards @@ -981,10 +1032,10 @@ contract NOPsSettlement is SetUp { (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); // register an upkeep and add funds - uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken), "", "", ""); - _mintERC20(UPKEEP_ADMIN, 1e20); + uint256 id = registry.registerUpkeep(address(TARGET1), 1000000, UPKEEP_ADMIN, 0, address(usdToken18), "", "", ""); + _mintERC20_18Decimals(UPKEEP_ADMIN, 1e20); vm.startPrank(UPKEEP_ADMIN); - usdToken.approve(address(registry), 1e20); + usdToken18.approve(address(registry), 1e20); registry.addFunds(id, 1e20); // manually call transmit so transmitters earn some rewards @@ -1025,10 +1076,10 @@ contract NOPsSettlement is SetUp { function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { IERC20[] memory billingTokens = new IERC20[](1); - billingTokens[0] = IERC20(address(usdToken)); + billingTokens[0] = IERC20(address(usdToken18)); uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100000000000000000000; // 100 USD + minRegistrationFees[0] = 100e18; // 100 USD address[] memory billingTokenAddresses = new address[](billingTokens.length); for (uint256 i = 0; i < billingTokens.length; i++) { @@ -1041,8 +1092,9 @@ contract NOPsSettlement is SetUp { gasFeePPB: 10_000_000, // 15% flatFeeMilliCents: 2_000, // 2 cents priceFeed: address(USDTOKEN_USD_FEED), - fallbackPrice: 100_000_000, // $1 - minSpend: 1000000000000000000 // 1 USD + fallbackPrice: 1e8, // $1 + minSpend: 1e18, // 1 USD + decimals: 18 }); address[] memory registrars = new address[](1); @@ -1245,7 +1297,7 @@ contract OnTokenTransfer is SetUp { function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { vm.startPrank(address(linkToken)); vm.expectRevert(Registry.InvalidToken.selector); - registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID)); + registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID18)); } function test_Happy() public { @@ -1257,20 +1309,42 @@ contract OnTokenTransfer is SetUp { } contract GetMinBalanceForUpkeep is SetUp { - function test_accountsForFlatFee() public { + function test_accountsForFlatFee_with18Decimals() public { // set fee to 0 - AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken)); + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken18)); usdTokenConfig.flatFeeMilliCents = 0; - _updateBillingTokenConfig(registry, address(usdToken), usdTokenConfig); + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID); + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID18); // set fee to non-zero usdTokenConfig.flatFeeMilliCents = 100; - _updateBillingTokenConfig(registry, address(usdToken), usdTokenConfig); + _updateBillingTokenConfig(registry, address(usdToken18), usdTokenConfig); - uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID); - assertEq(minBalanceAfter, minBalanceBefore + (uint256(usdTokenConfig.flatFeeMilliCents) * 1e13)); + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID18); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); + } + + function test_accountsForFlatFee_with6Decimals() public { + // set fee to 0 + AutomationRegistryBase2_3.BillingConfig memory usdTokenConfig = registry.getBillingTokenConfig(address(usdToken6)); + usdTokenConfig.flatFeeMilliCents = 0; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceBefore = registry.getMinBalanceForUpkeep(usdUpkeepID6); + + // set fee to non-zero + usdTokenConfig.flatFeeMilliCents = 100; + _updateBillingTokenConfig(registry, address(usdToken6), usdTokenConfig); + + uint256 minBalanceAfter = registry.getMinBalanceForUpkeep(usdUpkeepID6); + assertEq( + minBalanceAfter, + minBalanceBefore + ((uint256(usdTokenConfig.flatFeeMilliCents) * 1e13) / 10 ** (18 - usdTokenConfig.decimals)) + ); } } @@ -1346,29 +1420,29 @@ contract Transmit is SetUp { function test_handlesMixedBatchOfBillingTokens() external { uint256[] memory prevUpkeepBalances = new uint256[](3); prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); - prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID); + prevUpkeepBalances[1] = registry.getBalance(usdUpkeepID18); prevUpkeepBalances[2] = registry.getBalance(nativeUpkeepID); uint256[] memory prevTokenBalances = new uint256[](3); prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); prevTokenBalances[2] = weth.balanceOf(address(registry)); uint256[] memory prevReserveBalances = new uint256[](3); prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); prevReserveBalances[2] = registry.getReserveAmount(address(weth)); uint256[] memory upkeepIDs = new uint256[](3); upkeepIDs[0] = linkUpkeepID; - upkeepIDs[1] = usdUpkeepID; + upkeepIDs[1] = usdUpkeepID18; upkeepIDs[2] = nativeUpkeepID; // do the thing _transmit(upkeepIDs, registry); // assert upkeep balances have decreased require(prevUpkeepBalances[0] > registry.getBalance(linkUpkeepID), "link upkeep balance should have decreased"); - require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID), "usd upkeep balance should have decreased"); + require(prevUpkeepBalances[1] > registry.getBalance(usdUpkeepID18), "usd upkeep balance should have decreased"); require(prevUpkeepBalances[2] > registry.getBalance(nativeUpkeepID), "native upkeep balance should have decreased"); // assert token balances have not changed assertEq(prevTokenBalances[0], linkToken.balanceOf(address(registry))); - assertEq(prevTokenBalances[1], usdToken.balanceOf(address(registry))); + assertEq(prevTokenBalances[1], usdToken18.balanceOf(address(registry))); assertEq(prevTokenBalances[2], weth.balanceOf(address(registry))); // assert reserve amounts have adjusted accordingly require( @@ -1376,7 +1450,7 @@ contract Transmit is SetUp { "usd reserve amount should have increased" ); // link reserve amount increases in value equal to the decrease of the other reserve amounts require( - prevReserveBalances[1] > registry.getReserveAmount(address(usdToken)), + prevReserveBalances[1] > registry.getReserveAmount(address(usdToken18)), "usd reserve amount should have decreased" ); require( @@ -1398,7 +1472,7 @@ contract MigrateReceive is SetUp { (newRegistry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); idsToMigrate.push(linkUpkeepID); idsToMigrate.push(linkUpkeepID2); - idsToMigrate.push(usdUpkeepID); + idsToMigrate.push(usdUpkeepID18); idsToMigrate.push(nativeUpkeepID); registry.setPeerRegistryMigrationPermission(address(newRegistry), 1); newRegistry.setPeerRegistryMigrationPermission(address(registry), 2); @@ -1454,7 +1528,7 @@ contract MigrateReceive is SetUp { vm.startPrank(UPKEEP_ADMIN); // add some changes in upkeep data to the mix - registry.pauseUpkeep(usdUpkeepID); + registry.pauseUpkeep(usdUpkeepID18); registry.setUpkeepTriggerConfig(linkUpkeepID, randomBytes(100)); registry.setUpkeepCheckData(nativeUpkeepID, randomBytes(25)); @@ -1462,25 +1536,25 @@ contract MigrateReceive is SetUp { uint256[] memory prevUpkeepBalances = new uint256[](4); prevUpkeepBalances[0] = registry.getBalance(linkUpkeepID); prevUpkeepBalances[1] = registry.getBalance(linkUpkeepID2); - prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID); + prevUpkeepBalances[2] = registry.getBalance(usdUpkeepID18); prevUpkeepBalances[3] = registry.getBalance(nativeUpkeepID); uint256[] memory prevReserveBalances = new uint256[](3); prevReserveBalances[0] = registry.getReserveAmount(address(linkToken)); - prevReserveBalances[1] = registry.getReserveAmount(address(usdToken)); + prevReserveBalances[1] = registry.getReserveAmount(address(usdToken18)); prevReserveBalances[2] = registry.getReserveAmount(address(weth)); uint256[] memory prevTokenBalances = new uint256[](3); prevTokenBalances[0] = linkToken.balanceOf(address(registry)); - prevTokenBalances[1] = usdToken.balanceOf(address(registry)); + prevTokenBalances[1] = usdToken18.balanceOf(address(registry)); prevTokenBalances[2] = weth.balanceOf(address(registry)); bytes[] memory prevUpkeepData = new bytes[](4); prevUpkeepData[0] = abi.encode(registry.getUpkeep(linkUpkeepID)); prevUpkeepData[1] = abi.encode(registry.getUpkeep(linkUpkeepID2)); - prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID)); + prevUpkeepData[2] = abi.encode(registry.getUpkeep(usdUpkeepID18)); prevUpkeepData[3] = abi.encode(registry.getUpkeep(nativeUpkeepID)); bytes[] memory prevUpkeepTriggerData = new bytes[](4); prevUpkeepTriggerData[0] = registry.getUpkeepTriggerConfig(linkUpkeepID); prevUpkeepTriggerData[1] = registry.getUpkeepTriggerConfig(linkUpkeepID2); - prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID); + prevUpkeepTriggerData[2] = registry.getUpkeepTriggerConfig(usdUpkeepID18); prevUpkeepTriggerData[3] = registry.getUpkeepTriggerConfig(nativeUpkeepID); // event expectations @@ -1489,7 +1563,7 @@ contract MigrateReceive is SetUp { vm.expectEmit(address(registry)); emit UpkeepMigrated(linkUpkeepID2, prevUpkeepBalances[1], address(newRegistry)); vm.expectEmit(address(registry)); - emit UpkeepMigrated(usdUpkeepID, prevUpkeepBalances[2], address(newRegistry)); + emit UpkeepMigrated(usdUpkeepID18, prevUpkeepBalances[2], address(newRegistry)); vm.expectEmit(address(registry)); emit UpkeepMigrated(nativeUpkeepID, prevUpkeepBalances[3], address(newRegistry)); vm.expectEmit(address(newRegistry)); @@ -1497,7 +1571,7 @@ contract MigrateReceive is SetUp { vm.expectEmit(address(newRegistry)); emit UpkeepReceived(linkUpkeepID2, prevUpkeepBalances[1], address(registry)); vm.expectEmit(address(newRegistry)); - emit UpkeepReceived(usdUpkeepID, prevUpkeepBalances[2], address(registry)); + emit UpkeepReceived(usdUpkeepID18, prevUpkeepBalances[2], address(registry)); vm.expectEmit(address(newRegistry)); emit UpkeepReceived(nativeUpkeepID, prevUpkeepBalances[3], address(registry)); @@ -1507,11 +1581,11 @@ contract MigrateReceive is SetUp { // assert upkeep balances have been migrated assertEq(registry.getBalance(linkUpkeepID), 0); assertEq(registry.getBalance(linkUpkeepID2), 0); - assertEq(registry.getBalance(usdUpkeepID), 0); + assertEq(registry.getBalance(usdUpkeepID18), 0); assertEq(registry.getBalance(nativeUpkeepID), 0); assertEq(newRegistry.getBalance(linkUpkeepID), prevUpkeepBalances[0]); assertEq(newRegistry.getBalance(linkUpkeepID2), prevUpkeepBalances[1]); - assertEq(newRegistry.getBalance(usdUpkeepID), prevUpkeepBalances[2]); + assertEq(newRegistry.getBalance(usdUpkeepID18), prevUpkeepBalances[2]); assertEq(newRegistry.getBalance(nativeUpkeepID), prevUpkeepBalances[3]); // assert reserve balances have been adjusted @@ -1519,15 +1593,15 @@ contract MigrateReceive is SetUp { newRegistry.getReserveAmount(address(linkToken)), newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) ); - assertEq(newRegistry.getReserveAmount(address(usdToken)), newRegistry.getBalance(usdUpkeepID)); + assertEq(newRegistry.getReserveAmount(address(usdToken18)), newRegistry.getBalance(usdUpkeepID18)); assertEq(newRegistry.getReserveAmount(address(weth)), newRegistry.getBalance(nativeUpkeepID)); assertEq( newRegistry.getReserveAmount(address(linkToken)), prevReserveBalances[0] - registry.getReserveAmount(address(linkToken)) ); assertEq( - newRegistry.getReserveAmount(address(usdToken)), - prevReserveBalances[1] - registry.getReserveAmount(address(usdToken)) + newRegistry.getReserveAmount(address(usdToken18)), + prevReserveBalances[1] - registry.getReserveAmount(address(usdToken18)) ); assertEq( newRegistry.getReserveAmount(address(weth)), @@ -1539,20 +1613,23 @@ contract MigrateReceive is SetUp { linkToken.balanceOf(address(newRegistry)), newRegistry.getBalance(linkUpkeepID) + newRegistry.getBalance(linkUpkeepID2) ); - assertEq(usdToken.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID)); + assertEq(usdToken18.balanceOf(address(newRegistry)), newRegistry.getBalance(usdUpkeepID18)); assertEq(weth.balanceOf(address(newRegistry)), newRegistry.getBalance(nativeUpkeepID)); assertEq(linkToken.balanceOf(address(registry)), prevTokenBalances[0] - linkToken.balanceOf(address(newRegistry))); - assertEq(usdToken.balanceOf(address(registry)), prevTokenBalances[1] - usdToken.balanceOf(address(newRegistry))); + assertEq( + usdToken18.balanceOf(address(registry)), + prevTokenBalances[1] - usdToken18.balanceOf(address(newRegistry)) + ); assertEq(weth.balanceOf(address(registry)), prevTokenBalances[2] - weth.balanceOf(address(newRegistry))); // assert upkeep data matches assertEq(prevUpkeepData[0], abi.encode(newRegistry.getUpkeep(linkUpkeepID))); assertEq(prevUpkeepData[1], abi.encode(newRegistry.getUpkeep(linkUpkeepID2))); - assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID))); + assertEq(prevUpkeepData[2], abi.encode(newRegistry.getUpkeep(usdUpkeepID18))); assertEq(prevUpkeepData[3], abi.encode(newRegistry.getUpkeep(nativeUpkeepID))); assertEq(prevUpkeepTriggerData[0], newRegistry.getUpkeepTriggerConfig(linkUpkeepID)); assertEq(prevUpkeepTriggerData[1], newRegistry.getUpkeepTriggerConfig(linkUpkeepID2)); - assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID)); + assertEq(prevUpkeepTriggerData[2], newRegistry.getUpkeepTriggerConfig(usdUpkeepID18)); assertEq(prevUpkeepTriggerData[3], newRegistry.getUpkeepTriggerConfig(nativeUpkeepID)); vm.stopPrank(); diff --git a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol index eae07a8bab7..5ae9a29fc15 100644 --- a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol @@ -5,6 +5,7 @@ import "forge-std/Test.sol"; import {LinkToken} from "../../../shared/token/ERC677/LinkToken.sol"; import {ERC20Mock} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; +import {ERC20Mock6Decimals} from "../../mocks/ERC20Mock6Decimals.sol"; import {MockV3Aggregator} from "../../../tests/MockV3Aggregator.sol"; import {AutomationForwarderLogic} from "../../AutomationForwarderLogic.sol"; import {UpkeepTranscoder5_0 as Transcoder} from "../v2_3/UpkeepTranscoder5_0.sol"; @@ -16,7 +17,7 @@ import {AutomationRegistryLogicC2_3} from "../v2_3/AutomationRegistryLogicC2_3.s import {IAutomationRegistryMaster2_3 as Registry, AutomationRegistryBase2_3} from "../interfaces/v2_3/IAutomationRegistryMaster2_3.sol"; import {AutomationRegistrar2_3} from "../v2_3/AutomationRegistrar2_3.sol"; import {ChainModuleBase} from "../../chains/ChainModuleBase.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {MockUpkeep} from "../../mocks/MockUpkeep.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; import {WETH9} from "./WETH9.sol"; @@ -40,7 +41,8 @@ contract BaseTest is Test { // contracts LinkToken internal linkToken; - ERC20Mock internal usdToken; + ERC20Mock6Decimals internal usdToken6; + ERC20Mock internal usdToken18; WETH9 internal weth; MockV3Aggregator internal LINK_USD_FEED; MockV3Aggregator internal NATIVE_USD_FEED; @@ -73,7 +75,8 @@ contract BaseTest is Test { vm.startPrank(OWNER); linkToken = new LinkToken(); linkToken.grantMintRole(OWNER); - usdToken = new ERC20Mock("MOCK_ERC20", "MOCK_ERC20", OWNER, 0); + usdToken18 = new ERC20Mock("MOCK_ERC20_18Decimals", "MOCK_ERC20_18Decimals", OWNER, 0); + usdToken6 = new ERC20Mock6Decimals("MOCK_ERC20_6Decimals", "MOCK_ERC20_6Decimals", OWNER, 0); weth = new WETH9(); LINK_USD_FEED = new MockV3Aggregator(8, 2_000_000_000); // $20 @@ -114,14 +117,22 @@ contract BaseTest is Test { vm.deal(UPKEEP_ADMIN, 100 ether); vm.deal(FINANCE_ADMIN, 100 ether); vm.deal(STRANGER, 100 ether); + linkToken.mint(OWNER, 1000e18); linkToken.mint(UPKEEP_ADMIN, 1000e18); linkToken.mint(FINANCE_ADMIN, 1000e18); linkToken.mint(STRANGER, 1000e18); - usdToken.mint(OWNER, 1000e18); - usdToken.mint(UPKEEP_ADMIN, 1000e18); - usdToken.mint(FINANCE_ADMIN, 1000e18); - usdToken.mint(STRANGER, 1000e18); + + usdToken18.mint(OWNER, 1000e18); + usdToken18.mint(UPKEEP_ADMIN, 1000e18); + usdToken18.mint(FINANCE_ADMIN, 1000e18); + usdToken18.mint(STRANGER, 1000e18); + + usdToken6.mint(OWNER, 1000e6); + usdToken6.mint(UPKEEP_ADMIN, 1000e6); + usdToken6.mint(FINANCE_ADMIN, 1000e6); + usdToken6.mint(STRANGER, 1000e6); + weth.mint(OWNER, 1000e18); weth.mint(UPKEEP_ADMIN, 1000e18); weth.mint(FINANCE_ADMIN, 1000e18); @@ -154,14 +165,16 @@ contract BaseTest is Test { ) internal returns (Registry, AutomationRegistrar2_3) { Registry registry = deployRegistry(payoutMode); - IERC20[] memory billingTokens = new IERC20[](3); - billingTokens[0] = IERC20(address(usdToken)); + IERC20[] memory billingTokens = new IERC20[](4); + billingTokens[0] = IERC20(address(usdToken18)); billingTokens[1] = IERC20(address(weth)); billingTokens[2] = IERC20(address(linkToken)); + billingTokens[3] = IERC20(address(usdToken6)); uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); - minRegistrationFees[0] = 100000000000000000000; // 100 USD - minRegistrationFees[1] = 5000000000000000000; // 5 Native - minRegistrationFees[2] = 5000000000000000000; // 5 LINK + minRegistrationFees[0] = 100e18; // 100 USD + minRegistrationFees[1] = 5e18; // 5 Native + minRegistrationFees[2] = 5e18; // 5 LINK + minRegistrationFees[3] = 100e6; // 100 USD address[] memory billingTokenAddresses = new address[](billingTokens.length); for (uint256 i = 0; i < billingTokens.length; i++) { billingTokenAddresses[i] = address(billingTokens[i]); @@ -173,21 +186,32 @@ contract BaseTest is Test { flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 100_000_000, // $1 - minSpend: 1000000000000000000 // 1 USD + minSpend: 1e18, // 1 USD + decimals: 18 }); billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents priceFeed: address(NATIVE_USD_FEED), fallbackPrice: 100_000_000, // $1 - minSpend: 5000000000000000000 // 5 Native + minSpend: 5e18, // 5 Native + decimals: 18 }); billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ gasFeePPB: DEFAULT_GAS_FEE_PPB, // 10% flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents priceFeed: address(LINK_USD_FEED), fallbackPrice: 1_000_000_000, // $10 - minSpend: 1000000000000000000 // 1 LINK + minSpend: 1e18, // 1 LINK + decimals: 18 + }); + billingTokenConfigs[3] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 1e8, // $1 + minSpend: 1e6, // 1 USD + decimals: 6 }); if (payoutMode == AutoBase.PayoutMode.OFF_CHAIN) { @@ -418,10 +442,10 @@ contract BaseTest is Test { linkToken.mint(recipient, amount); } - /// @dev mints USDToken to the recipient - function _mintERC20(address recipient, uint256 amount) internal { + /// @dev mints USDToken with 18 decimals to the recipient + function _mintERC20_18Decimals(address recipient, uint256 amount) internal { vm.prank(OWNER); - usdToken.mint(recipient, amount); + usdToken18.mint(recipient, amount); } /// @dev returns a pseudo-random 32 bytes diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol index d4a6f90c313..ab9d7ae0b20 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistrar2_3.sol @@ -6,7 +6,7 @@ import {IAutomationRegistryMaster2_3} from "../interfaces/v2_3/IAutomationRegist import {TypeAndVersionInterface} from "../../../interfaces/TypeAndVersionInterface.sol"; import {ConfirmedOwner} from "../../../shared/access/ConfirmedOwner.sol"; import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol index d57a4ad6345..c95c2138f71 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistry2_3.sol @@ -9,7 +9,7 @@ import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; import {Chainable} from "../../Chainable.sol"; import {IERC677Receiver} from "../../../shared/interfaces/IERC677Receiver.sol"; import {OCR2Abstract} from "../../../shared/ocr2/OCR2Abstract.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; /** * @notice Registry for adding work for Chainlink nodes to perform on client diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol index 087d907ab44..275b25b28d0 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryBase2_3.sol @@ -11,7 +11,7 @@ import {AggregatorV3Interface} from "../../../shared/interfaces/AggregatorV3Inte import {LinkTokenInterface} from "../../../shared/interfaces/LinkTokenInterface.sol"; import {KeeperCompatibleInterface} from "../../interfaces/KeeperCompatibleInterface.sol"; import {IChainModule} from "../../interfaces/IChainModule.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; import {IWrappedNative} from "../interfaces/v2_3/IWrappedNative.sol"; @@ -58,8 +58,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // tx itself, but since payment processing itself takes gas, and it needs the overhead as input, we use fixed constants // to account for gas used in payment processing. These values are calibrated using hardhat tests which simulates various cases and verifies that // the variables result in accurate estimation - uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_000; // Fixed overhead per tx - uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 9_000; // Overhead per upkeep performed in batch + uint256 internal constant ACCOUNTING_FIXED_GAS_OVERHEAD = 51_200; // Fixed overhead per tx + uint256 internal constant ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD = 9_200; // Overhead per upkeep performed in batch LinkTokenInterface internal immutable i_link; AggregatorV3Interface internal immutable i_linkUSDFeed; @@ -375,6 +375,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint32 gasFeePPB; uint24 flatFeeMilliCents; // min fee is $0.00001, max fee is $167 AggregatorV3Interface priceFeed; + uint8 decimals; // 1st word, read in calculating BillingTokenPaymentParams uint256 fallbackPrice; // 2nd word only read if stale @@ -395,6 +396,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @dev this is a memory-only struct, so struct packing is less important */ struct BillingTokenPaymentParams { + uint8 decimals; uint32 gasFeePPB; uint24 flatFeeMilliCents; uint256 priceUSD; @@ -426,8 +428,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { /** * @notice struct containing receipt information about a payment or cost estimation - * @member gasCharge the amount to charge a user for gas spent - * @member premium the premium charged to the user, shared between all nodes + * @member gasCharge the amount to charge a user for gas spent using the billing token's native decimals + * @member premium the premium charged to the user, shared between all nodes, using the billing token's native decimals * @member gasReimbursementJuels the amount to reimburse a node for gas spent * @member premiumJuels the premium paid to NOPs, shared between all nodes */ @@ -633,6 +635,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { BillingConfig storage config = s_billingConfigs[billingToken]; paymentParams.flatFeeMilliCents = config.flatFeeMilliCents; paymentParams.gasFeePPB = config.gasFeePPB; + paymentParams.decimals = config.decimals; (, int256 feedValue, , uint256 timestamp, ) = config.priceFeed.latestRoundData(); if ( feedValue <= 0 || @@ -660,22 +663,38 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { HotVars memory hotVars, PaymentParams memory paymentParams ) internal view returns (PaymentReceipt memory receipt) { + uint256 decimals = paymentParams.billingTokenParams.decimals; uint256 gasWei = paymentParams.fastGasWei * hotVars.gasCeilingMultiplier; // in case it's actual execution use actual gas price, capped by fastGasWei * gasCeilingMultiplier if (paymentParams.isTransaction && tx.gasprice < gasWei) { gasWei = tx.gasprice; } + // scaling factor is based on decimals of billing token, and applies to premium and gasCharge + uint256 numeratorScalingFactor = decimals > 18 ? 10 ** (decimals - 18) : 1; + uint256 denominatorScalingFactor = decimals < 18 ? 10 ** (18 - decimals) : 1; + + // gas calculation uint256 gasPaymentHexaicosaUSD = (gasWei * (paymentParams.gasLimit + paymentParams.gasOverhead) + paymentParams.l1CostWei) * paymentParams.nativeUSD; // gasPaymentHexaicosaUSD has an extra 8 zeros because of decimals on nativeUSD feed - receipt.gasCharge = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.billingTokenParams.priceUSD); // has units of attoBillingToken, or "wei" + // gasCharge is scaled by the billing token's decimals + receipt.gasCharge = SafeCast.toUint96( + (gasPaymentHexaicosaUSD * numeratorScalingFactor) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); receipt.gasReimbursementJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); + + // premium calculation uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingTokenParams.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD uint256 premiumHexaicosaUSD = ((((gasWei * paymentParams.gasLimit) + paymentParams.l1CostWei) * paymentParams.billingTokenParams.gasFeePPB * paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; - receipt.premium = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.billingTokenParams.priceUSD); + // premium is scaled by the billing token's decimals + receipt.premium = SafeCast.toUint96( + (premiumHexaicosaUSD * numeratorScalingFactor) / + (paymentParams.billingTokenParams.priceUSD * denominatorScalingFactor) + ); receipt.premiumJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); return receipt; @@ -975,7 +994,9 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); + // balance is in the token's native decimals uint96 balance = upkeep.balance; + // payment is in the token's native decimals uint96 payment = receipt.gasCharge + receipt.premium; // this shouldn't happen, but in rare edge cases, we charge the full balance in case the user @@ -1064,6 +1085,11 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { IERC20 token = billingTokens[i]; BillingConfig memory config = billingConfigs[i]; + // most ERC20 tokens are 18 decimals, priceFeed must be 8 decimals + if (config.decimals != token.decimals() || config.priceFeed.decimals() != 8) { + revert InvalidToken(); + } + // if LINK is a billing option, payout mode must be ON_CHAIN if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { revert InvalidToken(); diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol index c08d6a0469a..99fc97ce5ce 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicA2_3.sol @@ -11,7 +11,7 @@ import {AutomationForwarder} from "../../AutomationForwarder.sol"; import {IAutomationForwarder} from "../../interfaces/IAutomationForwarder.sol"; import {UpkeepTranscoderInterfaceV2} from "../../interfaces/UpkeepTranscoderInterfaceV2.sol"; import {MigratableKeeperRegistryInterfaceV2} from "../../interfaces/MigratableKeeperRegistryInterfaceV2.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; /** diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol index 85d81e84b6f..d69d5e0bd96 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicB2_3.sol @@ -6,7 +6,7 @@ import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contra import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; import {AutomationRegistryLogicC2_3} from "./AutomationRegistryLogicC2_3.sol"; import {Chainable} from "../../Chainable.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {SafeERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/utils/SafeERC20.sol"; import {SafeCast} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/math/SafeCast.sol"; diff --git a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol index ef6a70333e0..0a429730bdb 100644 --- a/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol +++ b/contracts/src/v0.8/automation/dev/v2_3/AutomationRegistryLogicC2_3.sol @@ -6,7 +6,7 @@ import {EnumerableSet} from "../../../vendor/openzeppelin-solidity/v4.7.3/contra import {Address} from "../../../vendor/openzeppelin-solidity/v4.7.3/contracts/utils/Address.sol"; import {IAutomationForwarder} from "../../interfaces/IAutomationForwarder.sol"; import {IChainModule} from "../../interfaces/IChainModule.sol"; -import {IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/IERC20.sol"; +import {IERC20Metadata as IERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {IAutomationV21PlusCommon} from "../../interfaces/IAutomationV21PlusCommon.sol"; contract AutomationRegistryLogicC2_3 is AutomationRegistryBase2_3 { diff --git a/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol b/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol new file mode 100644 index 00000000000..63a61814e0d --- /dev/null +++ b/contracts/src/v0.8/automation/mocks/ERC20Mock6Decimals.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +import {ERC20Mock} from "../../vendor/openzeppelin-solidity/v4.8.3/contracts/mocks/ERC20Mock.sol"; + +// mock ERC20 with 6 decimals +contract ERC20Mock6Decimals is ERC20Mock { + constructor( + string memory name, + string memory symbol, + address initialAccount, + uint256 initialBalance + ) payable ERC20Mock(name, symbol, initialAccount, initialBalance) {} + + function decimals() public view virtual override returns (uint8) { + return 6; + } +} diff --git a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts index 47fc6f13e73..02191dab999 100644 --- a/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistrar2_3.test.ts @@ -232,6 +232,7 @@ describe('AutomationRegistrar2_3', () => { priceFeed: await registry.getLinkUSDFeedAddress(), fallbackPrice: 200, minSpend: minimumRegistrationAmount, + decimals: 18, }, ], ) diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts index 1036ab2ce88..e7480dd869a 100644 --- a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts @@ -667,6 +667,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: minUpkeepSpend, + decimals: 18, }, ], ) @@ -957,6 +958,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: minUpkeepSpend, + decimals: 18, }, ], ] @@ -976,6 +978,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: minUpkeepSpend, + decimals: 18, }, ], ] @@ -995,6 +998,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: minUpkeepSpend, + decimals: 18, }, ], ] @@ -4743,6 +4747,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: newMinUpkeepSpend, + decimals: 18, }, ], ) @@ -5258,6 +5263,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: newMinUpkeepSpend, + decimals: 18, }, ], ) @@ -5324,6 +5330,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: newMinUpkeepSpend, + decimals: 18, }, ], ) @@ -5385,6 +5392,7 @@ describe('AutomationRegistry2_3', () => { priceFeed: linkUSDFeed.address, fallbackPrice: fallbackLinkPrice, minSpend: newMinUpkeepSpend, + decimals: 18, }, ], ) diff --git a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go index 177c35fcea7..1f6c763d280 100644 --- a/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go +++ b/core/gethwrappers/generated/automation_registrar_wrapper2_3/automation_registrar_wrapper2_3.go @@ -57,7 +57,7 @@ type AutomationRegistrar23TriggerRegistrationStorage struct { } var AutomationRegistrarMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"LINKAddress\",\"type\":\"address\"},{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.InitialTriggerConfig[]\",\"name\":\"triggerConfigs\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minRegistrationFees\",\"type\":\"uint256[]\"},{\"internalType\":\"contractIWrappedNative\",\"name\":\"wrappedNativeToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"HashMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientPayment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAdminAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RequestNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"AutoApproveAllowedSenderSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ConfigChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"displayName\",\"type\":\"string\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"RegistrationApproved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"RegistrationRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"RegistrationRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"TriggerConfigSet\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"approve\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"cancel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"getAutoApproveAllowedSender\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMinimumRegistrationAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"hash\",\"type\":\"bytes32\"}],\"name\":\"getPendingRequest\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRegistry\",\"outputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"}],\"name\":\"getTriggerRegistrationDetails\",\"outputs\":[{\"components\":[{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"approvedCount\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistrar2_3.TriggerRegistrationStorage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_WRAPPED_NATIVE_TOKEN\",\"outputs\":[{\"internalType\":\"contractIWrappedNative\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"upkeepContract\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"adminAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"bytes\",\"name\":\"encryptedEmail\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structAutomationRegistrar2_3.RegistrationParams\",\"name\":\"requestParams\",\"type\":\"tuple\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"allowed\",\"type\":\"bool\"}],\"name\":\"setAutoApproveAllowedSender\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIAutomationRegistryMaster2_3\",\"name\":\"registry\",\"type\":\"address\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"minBalances\",\"type\":\"uint256[]\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"enumAutomationRegistrar2_3.AutoApproveType\",\"name\":\"autoApproveType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"autoApproveMaxAllowed\",\"type\":\"uint32\"}],\"name\":\"setTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", Bin: "0x60c06040523480156200001157600080fd5b5060405162003483380380620034838339810160408190526200003491620005db565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be8162000183565b5050506001600160a01b03808716608052811660a052620000e18584846200022e565b60005b84518110156200017657620001618582815181106200010757620001076200076d565b6020026020010151600001518683815181106200012857620001286200076d565b6020026020010151602001518784815181106200014957620001496200076d565b6020026020010151604001516200032a60201b60201c565b806200016d8162000783565b915050620000e4565b5050505050505062000804565b336001600160a01b03821603620001dd5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b62000238620003d8565b80518251146200025b57604051630dfe930960e41b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b03851617905560005b8251811015620002fb578181815181106200029857620002986200076d565b602002602001015160046000858481518110620002b957620002b96200076d565b60200260200101516001600160a01b03166001600160a01b03168152602001908152602001600020819055508080620002f29062000783565b91505062000279565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b62000334620003d8565b60ff83166000908152600660205260409020805483919060ff19166001836002811115620003665762000366620007ab565b021790555060ff831660009081526006602052604090819020805464ffffffff00191661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390620003cb90859085908590620007c1565b60405180910390a1505050565b6000546001600160a01b03163314620004345760405162461bcd60e51b815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000082565b565b6001600160a01b03811681146200044c57600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b604051606081016001600160401b03811182821017156200048a576200048a6200044f565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620004bb57620004bb6200044f565b604052919050565b60006001600160401b03821115620004df57620004df6200044f565b5060051b60200190565b600082601f830112620004fb57600080fd5b81516020620005146200050e83620004c3565b62000490565b82815260059290921b840181019181810190868411156200053457600080fd5b8286015b848110156200055c5780516200054e8162000436565b835291830191830162000538565b509695505050505050565b600082601f8301126200057957600080fd5b815160206200058c6200050e83620004c3565b82815260059290921b84018101918181019086841115620005ac57600080fd5b8286015b848110156200055c5780518352918301918301620005b0565b8051620005d68162000436565b919050565b60008060008060008060c08789031215620005f557600080fd5b8651620006028162000436565b80965050602080880151620006178162000436565b60408901519096506001600160401b03808211156200063557600080fd5b818a0191508a601f8301126200064a57600080fd5b81516200065b6200050e82620004c3565b81815260609091028301840190848101908d8311156200067a57600080fd5b938501935b8285101562000701576060858f0312156200069a5760008081fd5b620006a462000465565b855160ff81168114620006b75760008081fd5b81528587015160038110620006cc5760008081fd5b81880152604086015163ffffffff81168114620006e95760008081fd5b6040820152825260609490940193908501906200067f565b60608d015190995094505050808311156200071b57600080fd5b620007298b848c01620004e9565b955060808a01519250808311156200074057600080fd5b50506200075089828a0162000567565b9250506200076160a08801620005c9565b90509295509295509295565b634e487b7160e01b600052603260045260246000fd5b600060018201620007a457634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052602160045260246000fd5b60ff841681526060810160038410620007ea57634e487b7160e01b600052602160045260246000fd5b83602083015263ffffffff83166040830152949350505050565b60805160a051612c2f620008546000396000818161027b015281816105a601526106390152600081816104b301528181610a0301528181610a6c0152818161168501526116dc0152612c2f6000f3fe6080604052600436106101295760003560e01c806388b12d55116100a5578063accb832311610074578063befdae4611610059578063befdae46146104a1578063c4d252f5146104d5578063f2fde38b146104f557600080fd5b8063accb832314610461578063b5ff5b411461048157600080fd5b806388b12d55146103085780638da5cb5b146103d3578063a2b1ff94146103fe578063a4c0ed361461044157600080fd5b80635ab1bd53116100fc5780636bf7d75f116100e15780636bf7d75f1461026957806379ba50971461029d5780637e776f7f146102b257600080fd5b80635ab1bd53146101fd57806366ab87f91461024957600080fd5b8063181f5a771461012e578063212d08841461018d5780632ce3a14a146101ba578063367b9b4f146101db575b600080fd5b34801561013a57600080fd5b506101776040518060400160405280601981526020017f4175746f6d6174696f6e52656769737472617220322e332e300000000000000081525081565b6040516101849190611e6f565b60405180910390f35b34801561019957600080fd5b506101ad6101a8366004611e9f565b610515565b6040516101849190611f24565b6101cd6101c836600461223b565b6105a2565b604051908152602001610184565b3480156101e757600080fd5b506101fb6101f636600461227e565b610710565b005b34801561020957600080fd5b5060025473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610184565b34801561025557600080fd5b506101fb610264366004612346565b6107a2565b34801561027557600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156102a957600080fd5b506101fb6108e9565b3480156102be57600080fd5b506102f86102cd36600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205460ff1690565b6040519015158152602001610184565b34801561031457600080fd5b5061039a610323366004612439565b6000908152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff169483018590526001909301549092169301929092529091565b6040805173ffffffffffffffffffffffffffffffffffffffff90931683526bffffffffffffffffffffffff909116602083015201610184565b3480156103df57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610224565b34801561040a57600080fd5b506101cd61041936600461241c565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561044d57600080fd5b506101fb61045c366004612452565b6109eb565b34801561046d57600080fd5b506101fb61047c3660046124db565b610b19565b34801561048d57600080fd5b506101fb61049c366004612526565b610c84565b3480156104ad57600080fd5b506102247f000000000000000000000000000000000000000000000000000000000000000081565b3480156104e157600080fd5b506101fb6104f0366004612439565b610d63565b34801561050157600080fd5b506101fb61051036600461241c565b610f2a565b60408051606080820183526000808352602080840182905283850182905260ff86811683526006909152908490208451928301909452835492939192839116600281111561056557610565611eba565b600281111561057657610576611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015292915050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168260a0015173ffffffffffffffffffffffffffffffffffffffff1614801561060257503415155b156106bd5761061034610f3e565b82602001906bffffffffffffffffffffffff1690816bffffffffffffffffffffffff16815250507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561069f57600080fd5b505af11580156106b3573d6000803e3d6000fd5b5050505050610700565b610700333084602001516bffffffffffffffffffffffff168560a0015173ffffffffffffffffffffffffffffffffffffffff16610fe0909392919063ffffffff16565b61070a82336110c2565b92915050565b610718611529565b73ffffffffffffffffffffffffffffffffffffffff821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001685151590811790915591519182527f20c6237dac83526a849285a9f79d08a483291bdd3a056a0ef9ae94ecee1ad356910160405180910390a25050565b6107aa611529565b80518251146107e5576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851617905560005b82518110156108ba578181815181106108435761084361256f565b6020026020010151600460008584815181106108615761086161256f565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555080806108b2906125cd565b915050610828565b506040517fb9b6902016bd1219d5fa6161243b61e7e9f7f959526dd94ef8fa3e403bf881c390600090a1505050565b60015473ffffffffffffffffffffffffffffffffffffffff16331461096f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610a5a576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a688284018461223b565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168160a0015173ffffffffffffffffffffffffffffffffffffffff1614610af3576040517f018d10be00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6bffffffffffffffffffffffff84166020820152610b1181866110c2565b505050505050565b610b21611529565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290610bcd576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083604051602001610be091906126b9565b604051602081830303815290604052805190602001209050808314610c31576040517f3f4d605300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260056020526040812090815560010180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055610c7d610c7785612875565b826115ac565b5050505050565b610c8c611529565b60ff8316600090815260066020526040902080548391907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001836002811115610cd957610cd9611eba565b021790555060ff83166000908152600660205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ff1661010063ffffffff851602179055517f830a6d06a4e2caac67eba04323de22bdb04f032dd8b3d6a0c52b503d9a7036a390610d5690859085908590612881565b60405180910390a1505050565b6000818152600560209081526040918290208251606081018452815473ffffffffffffffffffffffffffffffffffffffff808216808452740100000000000000000000000000000000000000009092046bffffffffffffffffffffffff16948301949094526001909201549092169282019290925290331480610dfd575060005473ffffffffffffffffffffffffffffffffffffffff1633145b610e33576040517f61685c2b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805173ffffffffffffffffffffffffffffffffffffffff16610e81576040517f4b13b31e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600560209081526040808320928355600190920180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905582519083015191830151610efb9273ffffffffffffffffffffffffffffffffffffffff90911691906bffffffffffffffffffffffff1661198f565b60405182907f3663fb28ebc87645eb972c9dad8521bf665c623f287e79f1c56f1eb374b82a2290600090a25050565b610f32611529565b610f3b816119ea565b50565b60006bffffffffffffffffffffffff821115610fdc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610966565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526110bc9085907f23b872dd00000000000000000000000000000000000000000000000000000000906084015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152611adf565b50505050565b60a082015173ffffffffffffffffffffffffffffffffffffffff166000908152600460209081526040822054908401516bffffffffffffffffffffffff161015611138576040517fcd1c886700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b604083015173ffffffffffffffffffffffffffffffffffffffff16611189576040517f05bb467c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60025460a08401516040517fa538b2eb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291169063a538b2eb90602401602060405180830381865afa1580156111fd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061122191906128ac565b611257576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008360405160200161126a91906128c9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815281516020928301206000818152600590935291205490915073ffffffffffffffffffffffffffffffffffffffff16156112fd576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b836000015173ffffffffffffffffffffffffffffffffffffffff16817f7684390ebb103102f7f48c71439c2408713f8d437782a6fab2756acc0e42c1b78660c001518760e00151886060015189604001518a608001518b61012001518c61014001518d61010001518e6020015160405161137f99989796959493929190612a35565b60405180910390a3608084015160ff908116600090815260066020526040808220815160608101909252805492936114029383911660028111156113c5576113c5611eba565b60028111156113d6576113d6611eba565b8152905463ffffffff610100820481166020840152650100000000009091041660409091015285611beb565b1561146a57608085015160ff166000908152600660205260409020805465010000000000900463ffffffff1690600561143a83612af0565b91906101000a81548163ffffffff021916908363ffffffff1602179055505061146385836115ac565b9050611521565b604080516060810182528682015173ffffffffffffffffffffffffffffffffffffffff90811682526020808901516bffffffffffffffffffffffff90811682850190815260a08b01518416858701908152600089815260059094529590922093519151167401000000000000000000000000000000000000000002908216178255915160019091018054919092167fffffffffffffffffffffffff0000000000000000000000000000000000000000919091161790555b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146115aa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610966565b565b60025482516060840151604080860151608087015160a08801516101008901516101208a01516101408b015195517fc62cf68400000000000000000000000000000000000000000000000000000000815260009973ffffffffffffffffffffffffffffffffffffffff16988a988a9863c62cf6849861163c98939792969095939492939092909190600401612b13565b6020604051808303816000875af115801561165b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167f9190612ba1565b905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168660a0015173ffffffffffffffffffffffffffffffffffffffff16036117a6577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16634000aea08488602001518560405160200161172f91815260200190565b6040516020818303038152906040526040518463ffffffff1660e01b815260040161175c93929190612bba565b6020604051808303816000875af115801561177b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179f91906128ac565b90506118fa565b60a086015160208701516040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301526bffffffffffffffffffffffff909216602482015291169063095ea7b3906044016020604051808303816000875af1158015611833573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185791906128ac565b905080156118fa5760208601516040517f948108f7000000000000000000000000000000000000000000000000000000008152600481018490526bffffffffffffffffffffffff909116602482015273ffffffffffffffffffffffffffffffffffffffff84169063948108f790604401600060405180830381600087803b1580156118e157600080fd5b505af11580156118f5573d6000803e3d6000fd5b505050505b80611949576040517f39f1c8d900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff84166004820152602401610966565b81857fb9a292fb7e3edd920cd2d2829a3615a640c43fd7de0a0820aa0668feb4c37d4b8860c0015160405161197e9190611e6f565b60405180910390a350949350505050565b60405173ffffffffffffffffffffffffffffffffffffffff83166024820152604481018290526119e59084907fa9059cbb000000000000000000000000000000000000000000000000000000009060640161103a565b505050565b3373ffffffffffffffffffffffffffffffffffffffff821603611a69576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610966565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000611b41826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16611c909092919063ffffffff16565b8051909150156119e55780806020019051810190611b5f91906128ac565b6119e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610966565b60008083516002811115611c0157611c01611eba565b03611c0e5750600061070a565b600183516002811115611c2357611c23611eba565b148015611c56575073ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205460ff16155b15611c635750600061070a565b826020015163ffffffff16836040015163ffffffff161015611c875750600161070a565b50600092915050565b60606115218484600085856000808673ffffffffffffffffffffffffffffffffffffffff168587604051611cc49190612c06565b60006040518083038185875af1925050503d8060008114611d01576040519150601f19603f3d011682016040523d82523d6000602084013e611d06565b606091505b5091509150611d1787838387611d22565b979650505050505050565b60608315611db8578251600003611db15773ffffffffffffffffffffffffffffffffffffffff85163b611db1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610966565b5081611521565b6115218383815115611dcd5781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109669190611e6f565b60005b83811015611e1c578181015183820152602001611e04565b50506000910152565b60008151808452611e3d816020860160208601611e01565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000611e826020830184611e25565b9392505050565b803560ff81168114611e9a57600080fd5b919050565b600060208284031215611eb157600080fd5b611e8282611e89565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611f20577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b6000606082019050611f37828451611ee9565b602083015163ffffffff8082166020850152806040860151166040850152505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610160810167ffffffffffffffff81118282101715611fb057611fb0611f5d565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611ffd57611ffd611f5d565b604052919050565b73ffffffffffffffffffffffffffffffffffffffff81168114610f3b57600080fd5b8035611e9a81612005565b80356bffffffffffffffffffffffff81168114611e9a57600080fd5b803563ffffffff81168114611e9a57600080fd5b600082601f83011261207357600080fd5b813567ffffffffffffffff81111561208d5761208d611f5d565b6120be60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601611fb6565b8181528460208386010111156120d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000610160828403121561210357600080fd5b61210b611f8c565b905061211682612027565b815261212460208301612032565b602082015261213560408301612027565b60408201526121466060830161204e565b606082015261215760808301611e89565b608082015261216860a08301612027565b60a082015260c082013567ffffffffffffffff8082111561218857600080fd5b61219485838601612062565b60c084015260e08401359150808211156121ad57600080fd5b6121b985838601612062565b60e0840152610100915081840135818111156121d457600080fd5b6121e086828701612062565b8385015250610120915081840135818111156121fb57600080fd5b61220786828701612062565b83850152506101409150818401358181111561222257600080fd5b61222e86828701612062565b8385015250505092915050565b60006020828403121561224d57600080fd5b813567ffffffffffffffff81111561226457600080fd5b611521848285016120f0565b8015158114610f3b57600080fd5b6000806040838503121561229157600080fd5b823561229c81612005565b915060208301356122ac81612270565b809150509250929050565b600067ffffffffffffffff8211156122d1576122d1611f5d565b5060051b60200190565b600082601f8301126122ec57600080fd5b813560206123016122fc836122b7565b611fb6565b82815260059290921b8401810191818101908684111561232057600080fd5b8286015b8481101561233b5780358352918301918301612324565b509695505050505050565b60008060006060848603121561235b57600080fd5b833561236681612005565b925060208481013567ffffffffffffffff8082111561238457600080fd5b818701915087601f83011261239857600080fd5b81356123a66122fc826122b7565b81815260059190911b8301840190848101908a8311156123c557600080fd5b938501935b828510156123ec5784356123dd81612005565b825293850193908501906123ca565b96505050604087013592508083111561240457600080fd5b5050612412868287016122db565b9150509250925092565b60006020828403121561242e57600080fd5b8135611e8281612005565b60006020828403121561244b57600080fd5b5035919050565b6000806000806060858703121561246857600080fd5b843561247381612005565b935060208501359250604085013567ffffffffffffffff8082111561249757600080fd5b818701915087601f8301126124ab57600080fd5b8135818111156124ba57600080fd5b8860208285010111156124cc57600080fd5b95989497505060200194505050565b600080604083850312156124ee57600080fd5b823567ffffffffffffffff81111561250557600080fd5b8301610160818603121561251857600080fd5b946020939093013593505050565b60008060006060848603121561253b57600080fd5b61254484611e89565b925060208401356003811061255857600080fd5b91506125666040850161204e565b90509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036125fe576125fe61259e565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261263a57600080fd5b830160208101925035905067ffffffffffffffff81111561265a57600080fd5b80360382131561266957600080fd5b9250929050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526126e7602082016126cd84612027565b73ffffffffffffffffffffffffffffffffffffffff169052565b60006126f560208401612032565b6bffffffffffffffffffffffff811660408401525061271660408401612027565b73ffffffffffffffffffffffffffffffffffffffff811660608401525061273f6060840161204e565b63ffffffff811660808401525061275860808401611e89565b60ff811660a08401525061276e60a08401612027565b73ffffffffffffffffffffffffffffffffffffffff811660c08401525061279860c0840184612605565b6101608060e08601526127b061018086018385612670565b92506127bf60e0870187612605565b92507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008188870301818901526127f9868685612670565b9550612807818a018a612605565b9550925050610120818887030181890152612823868685612670565b9550612831818a018a612605565b955092505061014081888703018189015261284d868685612670565b955061285b818a018a612605565b955092505080878603018388015250611d17848483612670565b600061070a36836120f0565b60ff84168152606081016128986020830185611ee9565b63ffffffff83166040830152949350505050565b6000602082840312156128be57600080fd5b8151611e8281612270565b602081526128f060208201835173ffffffffffffffffffffffffffffffffffffffff169052565b6000602083015161291160408401826bffffffffffffffffffffffff169052565b50604083015173ffffffffffffffffffffffffffffffffffffffff8116606084015250606083015163ffffffff8116608084015250608083015160ff811660a08401525060a083015173ffffffffffffffffffffffffffffffffffffffff811660c08401525060c08301516101608060e0850152612993610180850183611e25565b915060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06101008187860301818801526129d18584611e25565b9450808801519250506101208187860301818801526129f08584611e25565b945080880151925050610140818786030181880152612a0f8584611e25565b908801518782039092018488015293509050612a2b8382611e25565b9695505050505050565b6000610120808352612a498184018d611e25565b90508281036020840152612a5d818c611e25565b905063ffffffff8a16604084015273ffffffffffffffffffffffffffffffffffffffff8916606084015260ff8816608084015282810360a0840152612aa28188611e25565b905082810360c0840152612ab68187611e25565b905082810360e0840152612aca8186611e25565b9150506bffffffffffffffffffffffff83166101008301529a9950505050505050505050565b600063ffffffff808316818103612b0957612b0961259e565b6001019392505050565b600061010073ffffffffffffffffffffffffffffffffffffffff808c16845263ffffffff8b166020850152808a16604085015260ff891660608501528088166080850152508060a0840152612b6a81840187611e25565b905082810360c0840152612b7e8186611e25565b905082810360e0840152612b928185611e25565b9b9a5050505050505050505050565b600060208284031215612bb357600080fd5b5051919050565b73ffffffffffffffffffffffffffffffffffffffff841681526bffffffffffffffffffffffff83166020820152606060408201526000612bfd6060830184611e25565b95945050505050565b60008251612c18818460208701611e01565b919091019291505056fea164736f6c6343000813000a", } diff --git a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go index c1d1edb04fb..891415c7d3a 100644 --- a/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_a_wrapper_2_3/automation_registry_logic_a_wrapper_2_3.go @@ -34,6 +34,7 @@ type AutomationRegistryBase23BillingConfig struct { GasFeePPB uint32 FlatFeeMilliCents *big.Int PriceFeed common.Address + Decimals uint8 FallbackPrice *big.Int MinSpend *big.Int } @@ -44,7 +45,7 @@ type AutomationRegistryBase23BillingOverrides struct { } var AutomationRegistryLogicAMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicB2_3\",\"name\":\"logicB\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicB2_3\",\"name\":\"logicB\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"enumAutomationRegistryBase2_3.Trigger\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"contractIERC20Metadata\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", Bin: "0x6101806040523480156200001257600080fd5b506040516200477c3803806200477c83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e0516101005161012051610140516101605161406862000714600039600081816088015260de01526000505060005050600081816111bd01526114d60152600050506000505060005050600050506140686000f3fe608060405260043610620000865760003560e01c80638e86139b11620000555780638e86139b1462000192578063c62cf68414620001b7578063c804802214620001eb578063f2fde38b14620002105762000086565b8063349e8cca14620000ce57806379ba5097146200012857806385c1b0ba14620001405780638da5cb5b1462000165575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015620000c7573d6000f35b3d6000fd5b005b348015620000db57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200013557600080fd5b50620000cc62000235565b3480156200014d57600080fd5b50620000cc6200015f36600462002cac565b62000338565b3480156200017257600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16620000fe565b3480156200019f57600080fd5b50620000cc620001b136600462002d85565b62001080565b348015620001c457600080fd5b50620001dc620001d636600462002f43565b62001408565b6040519081526020016200011f565b348015620001f857600080fd5b50620000cc6200020a36600462003038565b620017b5565b3480156200021d57600080fd5b50620000cc6200022f36600462003052565b62001c8d565b60015473ffffffffffffffffffffffffffffffffffffffff163314620002bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000377576200037762003079565b14158015620003c35750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff166003811115620003c057620003c062003079565b14155b15620003fb576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff166200044b576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000487576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e0810182905261010081018290528190819060008667ffffffffffffffff811115620004f157620004f162002df0565b6040519080825280602002602001820160405280156200051b578160200160208202803683370190505b50905060008767ffffffffffffffff8111156200053c576200053c62002df0565b604051908082528060200260200182016040528015620005d357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816200055b5790505b50905060008867ffffffffffffffff811115620005f457620005f462002df0565b6040519080825280602002602001820160405280156200062957816020015b6060815260200190600190039081620006135790505b50905060008967ffffffffffffffff8111156200064a576200064a62002df0565b6040519080825280602002602001820160405280156200067f57816020015b6060815260200190600190039081620006695790505b50905060008a67ffffffffffffffff811115620006a057620006a062002df0565b604051908082528060200260200182016040528015620006d557816020015b6060815260200190600190039081620006bf5790505b50905060005b8b81101562000def578c8c82818110620006f957620006f9620030a8565b602090810292909201356000818152600484526040808220815161012081018352815460ff8082161515835261010080830490911615159883019890985263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911694810194909452909a5091985050819003620008305786610100015199508660c001516bffffffffffffffffffffffff1698505b8973ffffffffffffffffffffffffffffffffffffffff1687610100015173ffffffffffffffffffffffffffffffffffffffff1614620008f55773ffffffffffffffffffffffffffffffffffffffff8a166000908152602160205260409020546200089c908a9062003106565b73ffffffffffffffffffffffffffffffffffffffff8b16600081815260216020526040902091909155620008d2908c8b62001ca5565b86610100015199508660c001516bffffffffffffffffffffffff1698506200091e565b80156200091e5760c08701516200091b906bffffffffffffffffffffffff168a6200311c565b98505b620009298862001d39565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d8116600483015290911690631a5da6c890602401600060405180830381600087803b1580156200099957600080fd5b505af1158015620009ae573d6000803e3d6000fd5b5050505086858281518110620009c857620009c8620030a8565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062000a1c5762000a1c620030a8565b73ffffffffffffffffffffffffffffffffffffffff9092166020928302919091018201526000898152600790915260409020805462000a5b9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000a899062003132565b801562000ada5780601f1062000aae5761010080835404028352916020019162000ada565b820191906000526020600020905b81548152906001019060200180831162000abc57829003601f168201915b505050505084828151811062000af45762000af4620030a8565b6020026020010181905250601d6000898152602001908152602001600020805462000b1f9062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000b4d9062003132565b801562000b9e5780601f1062000b725761010080835404028352916020019162000b9e565b820191906000526020600020905b81548152906001019060200180831162000b8057829003601f168201915b505050505083828151811062000bb85762000bb8620030a8565b6020026020010181905250601e6000898152602001908152602001600020805462000be39062003132565b80601f016020809104026020016040519081016040528092919081815260200182805462000c119062003132565b801562000c625780601f1062000c365761010080835404028352916020019162000c62565b820191906000526020600020905b81548152906001019060200180831162000c4457829003601f168201915b505050505082828151811062000c7c5762000c7c620030a8565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055600790925290812062000d029162002c0f565b6000888152601d6020526040812062000d1b9162002c0f565b6000888152601e6020526040812062000d349162002c0f565b600088815260066020526040902080547fffffffffffffffffffffffff000000000000000000000000000000000000000016905562000d7560028962001df0565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8d16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a28062000de68162003187565b915050620006db565b5073ffffffffffffffffffffffffffffffffffffffff891660009081526021602052604090205462000e2390899062003106565b73ffffffffffffffffffffffffffffffffffffffff8a1660008181526021602052604090209190915562000e59908b8a62001ca5565b60008c8c868167ffffffffffffffff81111562000e7a5762000e7a62002df0565b60405190808252806020026020018201604052801562000ea4578160200160208202803683370190505b508988888860405160200162000ec2989796959493929190620033b9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808f1693638e86139b939091169163c71249ab91600491869163aab9edd6918482019160209190819003860181865afa15801562000f72573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f98919062003498565b866040518463ffffffff1660e01b815260040162000fb993929190620034bd565b600060405180830381865afa15801562000fd7573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682016040526200101f9190810190620034e4565b6040518263ffffffff1660e01b81526004016200103d91906200355b565b600060405180830381600087803b1580156200105857600080fd5b505af11580156200106d573d6000803e3d6000fd5b5050505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620010a957620010a962003079565b14158015620010df57506003336000908152601c602052604090205460ff166003811115620010dc57620010dc62003079565b14155b1562001117576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008080808080806200112d888a018a62003882565b965096509650965096509650965060005b8751811015620013fc57600073ffffffffffffffffffffffffffffffffffffffff16878281518110620011755762001175620030a8565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff16036200128957858181518110620011b257620011b2620030a8565b6020026020010151307f0000000000000000000000000000000000000000000000000000000000000000604051620011ea9062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001234573d6000803e3d6000fd5b508782815181106200124a576200124a620030a8565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001341888281518110620012a257620012a2620030a8565b6020026020010151888381518110620012bf57620012bf620030a8565b6020026020010151878481518110620012dc57620012dc620030a8565b6020026020010151878581518110620012f957620012f9620030a8565b6020026020010151878681518110620013165762001316620030a8565b6020026020010151878781518110620013335762001333620030a8565b602002602001015162001e07565b878181518110620013565762001356620030a8565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a71888381518110620013945762001394620030a8565b602002602001015160c0015133604051620013df9291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a280620013f38162003187565b9150506200113e565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff1633148015906200143c57506200143a60093362002324565b155b1562001474576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b620014c3576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b620014ce8762002354565b905060008a307f0000000000000000000000000000000000000000000000000000000000000000604051620015039062002c4e565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f0801580156200154d573d6000803e3d6000fd5b5090506200163e826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062001e079050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c6200167683620039b3565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b604051620016ef92919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d87876040516200172b929190620039d9565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664856040516200176591906200355b565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850846040516200179f91906200355b565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915290620018d960005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa1580156200197b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620019a1919062003a26565b9050836060015163ffffffff16600003620019e8576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462001a2d576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215801562001a60575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b1562001a98576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8262001aae5762001aab6032826200311c565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff9092169190911790915562001b0b90600290879062001df016565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff16101562001b7e5760a085015162001b4c908462003a40565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff16111562001b7e575060c08401515b808560c0015162001b90919062003a40565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462001c229183169062003106565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b62001c97620025f3565b62001ca28162002678565b50565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262001d349084906200276f565b505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462001d97576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161462001ca2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062001dfe838362002882565b90505b92915050565b601454760100000000000000000000000000000000000000000000900460ff161562001e5f576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562001ec4576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062001f0a5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562001f42576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562001fad576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff9081166000908152602260205260409020546701000000000000009004166200201d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162002262919062003aba565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620022ad916bffffffffffffffffffffffff16906200311c565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d905220620022f2838262003aba565b506000868152601e602052604090206200230d828262003aba565b506200231b6002876200298d565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562001dfe565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620023d8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620023fe919062003a26565b6200240a919062003106565b6040518263ffffffff1660e01b81526004016200242991815260200190565b602060405180830381865afa15801562002447573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200246d919062003a26565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f8110156200258157838282815181106200253d576200253d620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620025788162003187565b9150506200251d565b5084600181111562002597576200259762003079565b60f81b81600f81518110620025b057620025b0620030a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620025ea8162003be1565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462002676576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401620002b3565b565b3373ffffffffffffffffffffffffffffffffffffffff821603620026f9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620002b3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000620027d3826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166200299b9092919063ffffffff16565b80519091501562001d345780806020019051810190620027f4919062003c24565b62001d34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401620002b3565b600081815260018301602052604081205480156200297b576000620028a960018362003106565b8554909150600090620028bf9060019062003106565b90508181146200292b576000866000018281548110620028e357620028e3620030a8565b9060005260206000200154905080876000018481548110620029095762002909620030a8565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806200293f576200293f62003c44565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062001e01565b600091505062001e01565b5092915050565b600062001dfe8383620029b4565b6060620029ac848460008562002a06565b949350505050565b6000818152600183016020526040812054620029fd5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562001e01565b50600062001e01565b60608247101562002a9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401620002b3565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162002ac5919062003c73565b60006040518083038185875af1925050503d806000811462002b04576040519150601f19603f3d011682016040523d82523d6000602084013e62002b09565b606091505b509150915062002b1c8783838762002b27565b979650505050505050565b6060831562002bc257825160000362002bba5773ffffffffffffffffffffffffffffffffffffffff85163b62002bba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620002b3565b5081620029ac565b620029ac838381511562002bd95781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620002b391906200355b565b50805462002c1d9062003132565b6000825580601f1062002c2e575050565b601f01602090049060005260206000209081019062001ca2919062002c5c565b6103ca8062003c9283390190565b5b8082111562002c73576000815560010162002c5d565b5090565b73ffffffffffffffffffffffffffffffffffffffff8116811462001ca257600080fd5b803562002ca78162002c77565b919050565b60008060006040848603121562002cc257600080fd5b833567ffffffffffffffff8082111562002cdb57600080fd5b818601915086601f83011262002cf057600080fd5b81358181111562002d0057600080fd5b8760208260051b850101111562002d1657600080fd5b6020928301955093505084013562002d2e8162002c77565b809150509250925092565b60008083601f84011262002d4c57600080fd5b50813567ffffffffffffffff81111562002d6557600080fd5b60208301915083602082850101111562002d7e57600080fd5b9250929050565b6000806020838503121562002d9957600080fd5b823567ffffffffffffffff81111562002db157600080fd5b62002dbf8582860162002d39565b90969095509350505050565b803563ffffffff8116811462002ca757600080fd5b80356002811062002ca757600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff8111828210171562002e465762002e4662002df0565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562002e965762002e9662002df0565b604052919050565b600067ffffffffffffffff82111562002ebb5762002ebb62002df0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011262002ef957600080fd5b813562002f1062002f0a8262002e9e565b62002e4c565b81815284602083860101111562002f2657600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060006101008a8c03121562002f6357600080fd5b62002f6e8a62002c9a565b985062002f7e60208b0162002dcb565b975062002f8e60408b0162002c9a565b965062002f9e60608b0162002de0565b955062002fae60808b0162002c9a565b945060a08a013567ffffffffffffffff8082111562002fcc57600080fd5b62002fda8d838e0162002d39565b909650945060c08c013591508082111562002ff457600080fd5b620030028d838e0162002ee7565b935060e08c01359150808211156200301957600080fd5b50620030288c828d0162002ee7565b9150509295985092959850929598565b6000602082840312156200304b57600080fd5b5035919050565b6000602082840312156200306557600080fd5b8135620030728162002c77565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562001e015762001e01620030d7565b8082018082111562001e015762001e01620030d7565b600181811c908216806200314757607f821691505b60208210810362003181577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620031bb57620031bb620030d7565b5060010190565b600081518084526020808501945080840160005b838110156200329b5781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a01919091526101009182015116908801526101209096019590820190600101620031d6565b509495945050505050565b600081518084526020808501945080840160005b838110156200329b57815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620032ba565b60005b838110156200330b578181015183820152602001620032f1565b50506000910152565b600081518084526200332e816020860160208601620032ee565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b600081518084526020808501808196508360051b8101915082860160005b85811015620033ac5782840389526200339984835162003314565b988501989350908401906001016200337e565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a1115620033f657600080fd5b8960051b808c838601378301838103820160208501526200341a8282018b620031c2565b9150508281036040840152620034318189620032a6565b90508281036060840152620034478188620032a6565b905082810360808401526200345d818762003360565b905082810360a084015262003473818662003360565b905082810360c084015262003489818562003360565b9b9a5050505050505050505050565b600060208284031215620034ab57600080fd5b815160ff811681146200307257600080fd5b60ff8416815260ff83166020820152606060408201526000620025ea606083018462003314565b600060208284031215620034f757600080fd5b815167ffffffffffffffff8111156200350f57600080fd5b8201601f810184136200352157600080fd5b80516200353262002f0a8262002e9e565b8181528560208385010111156200354857600080fd5b620025ea826020830160208601620032ee565b60208152600062001dfe602083018462003314565b600067ffffffffffffffff8211156200358d576200358d62002df0565b5060051b60200190565b600082601f830112620035a957600080fd5b81356020620035bc62002f0a8362003570565b82815260059290921b84018101918181019086841115620035dc57600080fd5b8286015b84811015620035f95780358352918301918301620035e0565b509695505050505050565b801515811462001ca257600080fd5b803562002ca78162003604565b80356fffffffffffffffffffffffffffffffff8116811462002ca757600080fd5b80356bffffffffffffffffffffffff8116811462002ca757600080fd5b600082601f8301126200367057600080fd5b813560206200368362002f0a8362003570565b8281526101209283028501820192828201919087851115620036a457600080fd5b8387015b858110156200377e5781818a031215620036c25760008081fd5b620036cc62002e1f565b620036d78262003613565b8152620036e686830162003613565b868201526040620036f981840162002dcb565b9082015260606200370c83820162002dcb565b9082015260806200371f83820162002c9a565b9082015260a06200373283820162003620565b9082015260c06200374583820162003641565b9082015260e06200375883820162002dcb565b908201526101006200376c83820162002c9a565b908201528452928401928101620036a8565b5090979650505050505050565b600082601f8301126200379d57600080fd5b81356020620037b062002f0a8362003570565b82815260059290921b84018101918181019086841115620037d057600080fd5b8286015b84811015620035f9578035620037ea8162002c77565b8352918301918301620037d4565b600082601f8301126200380a57600080fd5b813560206200381d62002f0a8362003570565b82815260059290921b840181019181810190868411156200383d57600080fd5b8286015b84811015620035f957803567ffffffffffffffff811115620038635760008081fd5b620038738986838b010162002ee7565b84525091830191830162003841565b600080600080600080600060e0888a0312156200389e57600080fd5b873567ffffffffffffffff80821115620038b757600080fd5b620038c58b838c0162003597565b985060208a0135915080821115620038dc57600080fd5b620038ea8b838c016200365e565b975060408a01359150808211156200390157600080fd5b6200390f8b838c016200378b565b965060608a01359150808211156200392657600080fd5b620039348b838c016200378b565b955060808a01359150808211156200394b57600080fd5b620039598b838c01620037f8565b945060a08a01359150808211156200397057600080fd5b6200397e8b838c01620037f8565b935060c08a01359150808211156200399557600080fd5b50620039a48a828b01620037f8565b91505092959891949750929550565b600063ffffffff808316818103620039cf57620039cf620030d7565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b60006020828403121562003a3957600080fd5b5051919050565b6bffffffffffffffffffffffff828116828216039080821115620029865762002986620030d7565b601f82111562001d3457600081815260208120601f850160051c8101602086101562003a915750805b601f850160051c820191505b8181101562003ab25782815560010162003a9d565b505050505050565b815167ffffffffffffffff81111562003ad75762003ad762002df0565b62003aef8162003ae8845462003132565b8462003a68565b602080601f83116001811462003b45576000841562003b0e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562003ab2565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101562003b945788860151825594840194600190910190840162003b73565b508582101562003bd157878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b8051602080830151919081101562003181577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b60006020828403121562003c3757600080fd5b8151620030728162003604565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000825162003c87818460208701620032ee565b919091019291505056fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", } @@ -5100,7 +5101,7 @@ func (AutomationRegistryLogicABillingConfigOverrideRemoved) Topic() common.Hash } func (AutomationRegistryLogicABillingConfigSet) Topic() common.Hash { - return common.HexToHash("0x720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c") + return common.HexToHash("0xca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba3") } func (AutomationRegistryLogicACancelledUpkeepReport) Topic() common.Hash { diff --git a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go index d26c12c1afd..04087c52e11 100644 --- a/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_logic_b_wrapper_2_3/automation_registry_logic_b_wrapper_2_3.go @@ -34,6 +34,7 @@ type AutomationRegistryBase23BillingConfig struct { GasFeePPB uint32 FlatFeeMilliCents *big.Int PriceFeed common.Address + Decimals uint8 FallbackPrice *big.Int MinSpend *big.Int } @@ -44,8 +45,8 @@ type AutomationRegistryBase23BillingOverrides struct { } var AutomationRegistryLogicBMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicC2_3\",\"name\":\"logicC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162005a3238038062005a3283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516152f86200073a60003960008181610182015261022f0152600081816120c5015261226b01526000612b910152600050506000612ec701526000613c3b01526000612fa1015260008181610c4701528181610d0801528181610dd30152612c5201526152f86000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e23660046142cc565b610511565b3480156101f357600080fd5b50610207610202366004614440565b610617565b604051610217949392919061455f565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f3660046145e1565b6108f5565b3480156102a057600080fd5b506101c56102af36600461462d565b610957565b3480156102c057600080fd5b506101c56102cf366004614646565b610b09565b3480156102e057600080fd5b506101c56102ef366004614672565b610d7c565b34801561030057600080fd5b5061031461030f366004614440565b611008565b60405161021797969594939291906146b3565b34801561033357600080fd5b506101c561034236600461462d565b61176c565b34801561035357600080fd5b506101c56103623660046142cc565b611802565b34801561037357600080fd5b506101c5611c7a565b34801561038857600080fd5b506101c561039736600461462d565b611d77565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e23660046145e1565b611f2c565b6101c56103f5366004614701565b611f81565b34801561040657600080fd5b506101c5610415366004614749565b612343565b34801561042657600080fd5b506101c561043536600461476e565b612442565b34801561044657600080fd5b5061045a6104553660046145e1565b612523565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c36600461462d565b6126ce565b34801561049d57600080fd5b506101c56104ac3660046145e1565b6128fb565b3480156104bd57600080fd5b506102076104cc3660046147e8565b6129b2565b3480156104dd57600080fd5b506101c56104ec3660046148ca565b612a74565b3480156104fd57600080fd5b5061031461050c36600461462d565b612a88565b61051a82612ac4565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b79565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906148f7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e09190614914565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a610833908561495f565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b8080602001905181019061087091906149c7565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ac4565b6000838152601d60205260409020610917828483614aac565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614c10565b60405180910390a2505050565b61096081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612bea565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c50565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614c24565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c50565b1215610e98576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190614c3f565b610f42919061495f565b905080821115610f88576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fa973ffffffffffffffffffffffffffffffffffffffff85168484612d1f565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061101c612b79565b60006110278a612df8565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a00151156113ea5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611760915050565b606083015163ffffffff908116146114345750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611760915050565b8251156114735750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611760915050565b61147c84612ea3565b8094508198508299505050506114a18e858786604001518b8b888a6101000151613095565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115035750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611760915050565b505060006115128d858e613405565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158d91906148f7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115cd9190614914565b60006040518083038160008787f1925050503d806000811461160b576040519150601f19603f3d011682016040523d82523d6000602084013e611610565b606091505b50915091505a611620908b61495f565b9950816116a6576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116855750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611760915050565b604090930151929a50600399505063ffffffff909116955061176092505050565b808060200190518101906116ba91906149c7565b909d509b508c6116f45750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611760915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101561174e5750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611760915050565b5050506040015163ffffffff16945050505b92959891949750929550565b6117746135e5565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561185a576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff81166118e9576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a29576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abd9190614c3f565b816060015163ffffffff161115611b00576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b6b90829061495f565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611bee9116846bffffffffffffffffffffffff8416612d1f565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611d8081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611eba576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611efc600283613636565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f3583612ac4565b6000838152601e60205260409020611f4e828483614aac565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614c10565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120bd576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415612159577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461214d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215634613642565b91505b818160c001516121699190614c58565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff16835260219091529020546121f991841690614c7d565b61010082015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040812091909155349003612269576101008101516122649073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff86166136e4565b6122f9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff161080612380575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123b7576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123c082612ac4565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61244a6135e5565b6000828152600460205260409020546601000000000000900463ffffffff908116146124a2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906124f08282614ca1565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124369190614d28565b60008061252e612b79565b601454760100000000000000000000000000000000000000000000900460ff1615612585576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126c193899089908190840183828082843760009201919091525061374892505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461280a576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612867576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61290483612ac4565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612966576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260076020526040902061297f828483614aac565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614c10565b600060606000806000634b56a42e60e01b8888886040516024016129d893929190614d5f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a618982610617565b929c919b50995090975095505050505050565b612a7c613963565b612a85816139e4565b50565b600060606000806000806000612aad8860405180602001604052806000815250611008565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b21576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612a85576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612be8576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612bf68383613ad9565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d109190614c3f565b612d1a9190614df5565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612df39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b28565b505050565b6000818160045b600f811015612e85577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e3d57612e3d614e15565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e7357506000949350505050565b80612e7d81614e44565b915050612dff565b5081600f1a6001811115612e9b57612e9b6144f5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190614e96565b5094509092505050600081131580612f6b57508142105b80612f8c5750828015612f8c5750612f83824261495f565b8463ffffffff16105b15612f9b576019549650612f9f565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561300a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302e9190614e96565b509450909250505060008113158061304557508142105b806130665750828015613066575061305d824261495f565b8463ffffffff16105b1561307557601a549550613079565b8095505b86866130848a613c34565b965096509650505050509193909250565b60008080808960018111156130ac576130ac6144f5565b036130bb575062016b48613110565b60018960018111156130cf576130cf6144f5565b036130de57506201ccf0613110565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131239190614ee6565b6131319060ff166040614eff565b60185461315f906103a49074010000000000000000000000000000000000000000900463ffffffff16614c7d565b6131699190614c7d565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fe9190614f16565b90925090508183613210836018614c7d565b61321a9190614eff565b60808f015161322a906001614ee6565b6132399060ff166115e0614eff565b6132439190614c7d565b61324d9190614c7d565b6132579085614c7d565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ee9190614c3f565b8d6060015161ffff166133019190614eff565b945050505060006133128b86613d25565b60008d815260046020526040902054909150610100900460ff16156133775760008c81526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845284529151909116908201525b60006133e18c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613e76565b602081015181519192506133f491614c58565b9d9c50505050505050505050505050565b6060600083600181111561341b5761341b6144f5565b036134e4576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161346091602401614fd5565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290506135de565b60018360018111156134f8576134f86144f5565b036130de57600082806020019051810190613513919061504e565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161355891849160240161515e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506135de9050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bf68383614046565b60006bffffffffffffffffffffffff8211156136e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137429085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d71565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137a5576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061381a908590602401615229565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906138ed908790879060040161523c565b60408051808303816000875af115801561390b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392f9190615255565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b2057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612bf9565b506000612bf9565b6000613b8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166141399092919063ffffffff16565b805190915015612df35780806020019051810190613ba89190614c24565b612df3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc89190614e96565b50935050925050600082131580613cde57508042105b80613d0e57506000846040015162ffffff16118015613d0e5750613d02814261495f565b846040015162ffffff16105b15613d1e575050601b5492915050565b5092915050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa158015613de7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e0b9190614e96565b50935050925050600082131580613e2157508042105b80613e5157506000866040015162ffffff16118015613e515750613e45814261495f565b866040015162ffffff16105b15613e655760018301546040850152613e6d565b604084018290525b50505092915050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff168360600151613eb49190614eff565b90508261010001518015613ec75750803a105b15613ecf57503a5b60008360a00151846040015185602001518660000151613eef9190614c7d565b613ef99085614eff565b613f039190614c7d565b613f0d9190614eff565b9050613f2b8460e001516040015182613f269190615281565b613642565b6bffffffffffffffffffffffff1683526080840151613f4e90613f269083615281565b6bffffffffffffffffffffffff16604084015260e084015160200151600090613f859062ffffff16683635c9adc5dea00000614eff565b9050600081633b9aca008760a001518860e001516000015163ffffffff1689604001518a6000015189613fb89190614eff565b613fc29190614c7d565b613fcc9190614eff565b613fd69190614eff565b613fe09190615281565b613fea9190614c7d565b90506140038660e001516040015182613f269190615281565b6bffffffffffffffffffffffff166020860152608086015161402990613f269083615281565b6bffffffffffffffffffffffff1660608601525050505092915050565b6000818152600183016020526040812054801561412f57600061406a60018361495f565b855490915060009061407e9060019061495f565b90508181146140e357600086600001828154811061409e5761409e614e15565b90600052602060002001549050808760000184815481106140c1576140c1614e15565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806140f4576140f46152bc565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612bf9565b6000915050612bf9565b6060612e9b8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161416d9190614914565b60006040518083038185875af1925050503d80600081146141aa576040519150601f19603f3d011682016040523d82523d6000602084013e6141af565b606091505b50915091506141c0878383876141cb565b979650505050505050565b6060831561426157825160000361425a5773ffffffffffffffffffffffffffffffffffffffff85163b61425a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612e9b565b612e9b83838151156142765781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab9190615229565b73ffffffffffffffffffffffffffffffffffffffff81168114612a8557600080fd5b600080604083850312156142df57600080fd5b8235915060208301356142f1816142aa565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff8111828210171561434f5761434f6142fc565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561439c5761439c6142fc565b604052919050565b600067ffffffffffffffff8211156143be576143be6142fc565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126143fb57600080fd5b813561440e614409826143a4565b614355565b81815284602083860101111561442357600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561445357600080fd5b82359150602083013567ffffffffffffffff81111561447157600080fd5b61447d858286016143ea565b9150509250929050565b60005b838110156144a257818101518382015260200161448a565b50506000910152565b600081518084526144c3816020860160208601614487565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061455b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061457a60808301866144ab565b90506145896040830185614524565b82606083015295945050505050565b60008083601f8401126145aa57600080fd5b50813567ffffffffffffffff8111156145c257600080fd5b6020830191508360208285010111156145da57600080fd5b9250929050565b6000806000604084860312156145f657600080fd5b83359250602084013567ffffffffffffffff81111561461457600080fd5b61462086828701614598565b9497909650939450505050565b60006020828403121561463f57600080fd5b5035919050565b6000806040838503121561465957600080fd5b8235614664816142aa565b946020939093013593505050565b60008060006060848603121561468757600080fd5b8335614692816142aa565b925060208401356146a2816142aa565b929592945050506040919091013590565b871515815260e0602082015260006146ce60e08301896144ab565b90506146dd6040830188614524565b8560608301528460808301528360a08301528260c083015298975050505050505050565b6000806040838503121561471457600080fd5b8235915060208301356bffffffffffffffffffffffff811681146142f157600080fd5b63ffffffff81168114612a8557600080fd5b6000806040838503121561475c57600080fd5b8235915060208301356142f181614737565b600080828403606081121561478257600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820112156147b657600080fd5b506020830190509250929050565b600067ffffffffffffffff8211156147de576147de6142fc565b5060051b60200190565b600080600080606085870312156147fe57600080fd5b8435935060208086013567ffffffffffffffff8082111561481e57600080fd5b818801915088601f83011261483257600080fd5b8135614840614409826147c4565b81815260059190911b8301840190848101908b83111561485f57600080fd5b8585015b838110156148975780358581111561487b5760008081fd5b6148898e89838a01016143ea565b845250918601918601614863565b509750505060408801359250808311156148b057600080fd5b50506148be87828801614598565b95989497509550505050565b6000602082840312156148dc57600080fd5b81356135de816142aa565b80516148f2816142aa565b919050565b60006020828403121561490957600080fd5b81516135de816142aa565b60008251614926818460208701614487565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612bf957612bf9614930565b805180151581146148f257600080fd5b600082601f83011261499357600080fd5b81516149a1614409826143a4565b8181528460208386010111156149b657600080fd5b612e9b826020830160208701614487565b600080604083850312156149da57600080fd5b6149e383614972565b9150602083015167ffffffffffffffff8111156149ff57600080fd5b61447d85828601614982565b600181811c90821680614a1f57607f821691505b602082108103614a58577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612df357600081815260208120601f850160051c81016020861015614a855750805b601f850160051c820191505b81811015614aa457828155600101614a91565b505050505050565b67ffffffffffffffff831115614ac457614ac46142fc565b614ad883614ad28354614a0b565b83614a5e565b6000601f841160018114614b2a5760008515614af45750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614bc0565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614b795786850135825560209485019460019092019101614b59565b5086821015614bb4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612e9b602083018486614bc7565b600060208284031215614c3657600080fd5b612bf682614972565b600060208284031215614c5157600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d1e57613d1e614930565b80820180821115612bf957612bf9614930565b62ffffff81168114612a8557600080fd5b8135614cac81614737565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614cec81614c90565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614d3781614737565b63ffffffff1682526020830135614d4d81614c90565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614dd4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614dc28683516144ab565b95509382019390820190600101614d88565b505085840381870152505050614deb818587614bc7565b9695505050505050565b8181036000831280158383131683831282161715613d1e57613d1e614930565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614e7557614e75614930565b5060010190565b805169ffffffffffffffffffff811681146148f257600080fd5b600080600080600060a08688031215614eae57600080fd5b614eb786614e7c565b9450602086015193506040860151925060608601519150614eda60808701614e7c565b90509295509295909350565b60ff8181168382160190811115612bf957612bf9614930565b8082028115828204841417612bf957612bf9614930565b60008060408385031215614f2957600080fd5b505080516020909101519092909150565b60008154614f4781614a0b565b808552602060018381168015614f645760018114614f9c57614fca565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b8901019550614fca565b866000528260002060005b85811015614fc25781548a8201860152908301908401614fa7565b890184019650505b505050505092915050565b602081526000612bf66020830184614f3a565b600082601f830112614ff957600080fd5b81516020615009614409836147c4565b82815260059290921b8401810191818101908684111561502857600080fd5b8286015b84811015615043578051835291830191830161502c565b509695505050505050565b60006020828403121561506057600080fd5b815167ffffffffffffffff8082111561507857600080fd5b90830190610100828603121561508d57600080fd5b61509561432b565b82518152602083015160208201526040830151604082015260608301516060820152608083015160808201526150cd60a084016148e7565b60a082015260c0830151828111156150e457600080fd5b6150f087828601614fe8565b60c08301525060e08301518281111561510857600080fd5b61511487828601614982565b60e08301525095945050505050565b600081518084526020808501945080840160005b8381101561515357815187529582019590820190600101615137565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506151cf610140840182615123565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08483030161012085015261520b82826144ab565b91505082810360208401526152208185614f3a565b95945050505050565b602081526000612bf660208301846144ab565b828152604060208201526000612e9b60408301846144ab565b6000806040838503121561526857600080fd5b61527183614972565b9150602083015190509250929050565b6000826152b7577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicC2_3\",\"name\":\"logicC\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"enumAutomationRegistryBase2_3.UpkeepFailureReason\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contractIERC20Metadata\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6101806040523480156200001257600080fd5b5060405162005c0e38038062005c0e83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516154d46200073a60003960008181610182015261022f0152600081816120c5015261226b01526000612b910152600050506000612ec701526000613c3b01526000612fa1015260008181610c4701528181610d0801528181610dd30152612c5201526154d46000f3fe6080604052600436106101805760003560e01c80638765ecbe116100d6578063aed2e9291161007f578063ce7dc5b411610059578063ce7dc5b4146104b1578063f2fde38b146104d1578063f7d334ba146104f157610180565b8063aed2e9291461043a578063b148ab6b14610471578063cd7f71b51461049157610180565b8063948108f7116100b0578063948108f7146103e7578063a72aa27e146103fa578063a86e17811461041a57610180565b80638765ecbe1461037c5780638da5cb5b1461039c5780638dcf0fe7146103c757610180565b806354b7faae1161013857806371fae17f1161011257806371fae17f14610327578063744bfe611461034757806379ba50971461036757610180565b806354b7faae146102b457806368d369d8146102d457806371791aa0146102f457610180565b8063349e8cca11610169578063349e8cca146102205780634ee88d35146102745780635165f2f51461029457610180565b80631a2af011146101c757806329c5efad146101e7575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101c0573d6000f35b3d6000fd5b005b3480156101d357600080fd5b506101c56101e236600461437c565b610511565b3480156101f357600080fd5b506102076102023660046144f0565b610617565b604051610217949392919061460f565b60405180910390f35b34801561022c57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610217565b34801561028057600080fd5b506101c561028f366004614691565b6108f5565b3480156102a057600080fd5b506101c56102af3660046146dd565b610957565b3480156102c057600080fd5b506101c56102cf3660046146f6565b610b09565b3480156102e057600080fd5b506101c56102ef366004614722565b610d7c565b34801561030057600080fd5b5061031461030f3660046144f0565b611008565b6040516102179796959493929190614763565b34801561033357600080fd5b506101c56103423660046146dd565b61176c565b34801561035357600080fd5b506101c561036236600461437c565b611802565b34801561037357600080fd5b506101c5611c7a565b34801561038857600080fd5b506101c56103973660046146dd565b611d77565b3480156103a857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661024f565b3480156103d357600080fd5b506101c56103e2366004614691565b611f2c565b6101c56103f53660046147b1565b611f81565b34801561040657600080fd5b506101c56104153660046147f9565b612343565b34801561042657600080fd5b506101c561043536600461481e565b612442565b34801561044657600080fd5b5061045a610455366004614691565b612523565b604080519215158352602083019190915201610217565b34801561047d57600080fd5b506101c561048c3660046146dd565b6126ce565b34801561049d57600080fd5b506101c56104ac366004614691565b6128fb565b3480156104bd57600080fd5b506102076104cc366004614898565b6129b2565b3480156104dd57600080fd5b506101c56104ec36600461497a565b612a74565b3480156104fd57600080fd5b5061031461050c3660046146dd565b612a88565b61051a82612ac4565b3373ffffffffffffffffffffffffffffffffffffffff821603610569576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146106135760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b60006060600080610626612b79565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561077c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107a091906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107e091906149c4565b60006040518083038160008787f1925050503d806000811461081e576040519150601f19603f3d011682016040523d82523d6000602084013e610823565b606091505b50915091505a6108339085614a0f565b93508161085c5760006040518060200160405280600081525060079650965096505050506108ec565b808060200190518101906108709190614a77565b90975095508661089c5760006040518060200160405280600081525060049650965096505050506108ec565b60185486517401000000000000000000000000000000000000000090910463ffffffff1610156108e85760006040518060200160405280600081525060059650965096505050506108ec565b5050505b92959194509250565b6108fe83612ac4565b6000838152601d60205260409020610917828483614b5c565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d5664838360405161094a929190614cc0565b60405180910390a2505050565b61096081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a9a576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610ad9600283612bea565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610b11612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610b5e576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b68612c50565b90506000811215610bb4576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610bf8576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cb69190614cd4565b905080610cef576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610d6e91815260200190565b60405180910390a350505050565b610d84612bff565b73ffffffffffffffffffffffffffffffffffffffff8216610dd1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e56576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e60612c50565b1215610e98576040517f981bb6a000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610f14573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f389190614cef565b610f429190614a0f565b905080821115610f88576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610bab565b610fa973ffffffffffffffffffffffffffffffffffffffff85168484612d1f565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610d6e91815260200190565b60006060600080600080600061101c612b79565b60006110278a612df8565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a00151156113ea5750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff169450859350839250611760915050565b606083015163ffffffff908116146114345750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff169450859350839250611760915050565b8251156114735750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff169450859350839250611760915050565b61147c84612ea3565b8094508198508299505050506114a18e858786604001518b8b888a6101000151613095565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff1610156115035750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff169450859350839250611760915050565b505060006115128d858e613405565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015611569573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061158d91906149a7565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16846040516115cd91906149c4565b60006040518083038160008787f1925050503d806000811461160b576040519150601f19603f3d011682016040523d82523d6000602084013e611610565b606091505b50915091505a611620908b614a0f565b9950816116a6576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156116855750506040805160208101825260008082529390910151929b509950600898505063ffffffff169450611760915050565b604090930151929a50600399505063ffffffff909116955061176092505050565b808060200190518101906116ba9190614a77565b909d509b508c6116f45750506040805160208101825260008082529390910151929b509950600498505063ffffffff169450611760915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101561174e5750506040805160208101825260008082529390910151929b509950600598505063ffffffff169450611760915050565b5050506040015163ffffffff16945050505b92959891949750929550565b6117746135e5565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff161561185a576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff81166118e9576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611a29576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abd9190614cef565b816060015163ffffffff161115611b00576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690611b6b908290614a0f565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551611bee9116846bffffffffffffffffffffffff8416612d1f565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611cfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610bab565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b611d8081612ac4565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611eba576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611efc600283613636565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b611f3583612ac4565b6000838152601e60205260409020611f4e828483614b5c565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf4850838360405161094a929190614cc0565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146120bd576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415612159577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461214d576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61215634613642565b91505b818160c001516121699190614d08565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff16835260219091529020546121f991841690614d2d565b61010082015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040812091909155349003612269576101008101516122649073ffffffffffffffffffffffffffffffffffffffff1633306bffffffffffffffffffffffff86166136e4565b6122f9565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b1580156122df57600080fd5b505af11580156122f3573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff161080612380575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b156123b7576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6123c082612ac4565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b61244a6135e5565b6000828152600460205260409020546601000000000000900463ffffffff908116146124a2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790556023909152902081906124f08282614d51565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b340826040516124369190614dd8565b60008061252e612b79565b601454760100000000000000000000000000000000000000000000900460ff1615612585576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936126c193899089908190840183828082843760009201919091525061374892505050565b9097909650945050505050565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461280a576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612867576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b61290483612ac4565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115612966576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260076020526040902061297f828483614b5c565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d838360405161094a929190614cc0565b600060606000806000634b56a42e60e01b8888886040516024016129d893929190614e0f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612a618982610617565b929c919b50995090975095505050505050565b612a7c613963565b612a85816139e4565b50565b600060606000806000806000612aad8860405180602001604052806000815250611008565b959e949d50929b5090995097509550909350915050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314612b21576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612a85576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612be8576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000612bf68383613ad9565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015612cec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d109190614cef565b612d1a9190614ea5565b905090565b60405173ffffffffffffffffffffffffffffffffffffffff8316602482015260448101829052612df39084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613b28565b505050565b6000818160045b600f811015612e85577fff000000000000000000000000000000000000000000000000000000000000008216838260208110612e3d57612e3d614ec5565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614612e7357506000949350505050565b80612e7d81614ef4565b915050612dff565b5081600f1a6001811115612e9b57612e9b6145a5565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015612f30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f549190614f46565b5094509092505050600081131580612f6b57508142105b80612f8c5750828015612f8c5750612f838242614a0f565b8463ffffffff16105b15612f9b576019549650612f9f565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561300a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302e9190614f46565b509450909250505060008113158061304557508142105b806130665750828015613066575061305d8242614a0f565b8463ffffffff16105b1561307557601a549550613079565b8095505b86866130848a613c34565b965096509650505050509193909250565b60008080808960018111156130ac576130ac6145a5565b036130bb575062016b48613110565b60018960018111156130cf576130cf6145a5565b036130de57506201ccf0613110565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a6080015160016131239190614f96565b6131319060ff166040614faf565b60185461315f906103a49074010000000000000000000000000000000000000000900463ffffffff16614d2d565b6131699190614d2d565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa1580156131da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131fe9190614fc6565b90925090508183613210836018614d2d565b61321a9190614faf565b60808f015161322a906001614f96565b6132399060ff166115e0614faf565b6132439190614d2d565b61324d9190614d2d565b6132579085614d2d565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa1580156132ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132ee9190614cef565b8d6060015161ffff166133019190614faf565b945050505060006133128b86613d25565b60008d815260046020526040902054909150610100900460ff16156133775760008c81526023602090815260409182902082518084018452905463ffffffff811680835264010000000090910462ffffff908116928401928352928501525116908201525b60006133e18c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff16815260200185815260200160001515815250613ea1565b602081015181519192506133f491614d08565b9d9c50505050505050505050505050565b6060600083600181111561341b5761341b6145a5565b036134e4576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009161346091602401615085565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915290506135de565b60018360018111156134f8576134f86145a5565b036130de5760008280602001905181019061351391906150fe565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009161355891849160240161520e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915291506135de9050565b9392505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612bf683836140f6565b60006bffffffffffffffffffffffff8211156136e0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610bab565b5090565b60405173ffffffffffffffffffffffffffffffffffffffff808516602483015283166044820152606481018290526137429085907f23b872dd0000000000000000000000000000000000000000000000000000000090608401612d71565b50505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156137a5576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061381a9085906024016152d9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906138ed90879087906004016152ec565b60408051808303816000875af115801561390b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061392f9190615305565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612be8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610bab565b3373ffffffffffffffffffffffffffffffffffffffff821603613a63576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610bab565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000818152600183016020526040812054613b2057508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612bf9565b506000612bf9565b6000613b8a826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166141e99092919063ffffffff16565b805190915015612df35780806020019051810190613ba89190614cd4565b612df3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bab565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613ca4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cc89190614f46565b50935050925050600082131580613cde57508042105b80613d0e57506000846040015162ffffff16118015613d0e5750613d028142614a0f565b846040015162ffffff16105b15613d1e575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613e12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e369190614f46565b50935050925050600082131580613e4c57508042105b80613e7c57506000866040015162ffffff16118015613e7c5750613e708142614a0f565b866040015162ffffff16105b15613e905760018301546060850152613e98565b606084018290525b50505092915050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff168460600151613eef9190614faf565b90508361010001518015613f025750803a105b15613f0a57503a5b600060128311613f1b576001613f31565b613f26601284614a0f565b613f3190600a615451565b9050600060128410613f44576001613f5a565b613f4f846012614a0f565b613f5a90600a615451565b905060008660a00151876040015188602001518960000151613f7c9190614d2d565b613f869087614faf565b613f909190614d2d565b613f9a9190614faf565b9050613fcc828860e0015160600151613fb39190614faf565b613fbd8584614faf565b613fc7919061545d565b613642565b6bffffffffffffffffffffffff1686526080870151613fef90613fc7908361545d565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906140289062ffffff16683635c9adc5dea00000614faf565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61405b9190614faf565b6140659190614d2d565b61406f9190614faf565b6140799190614faf565b614083919061545d565b61408d9190614d2d565b90506140b0848a60e00151606001516140a69190614faf565b613fbd8784614faf565b6bffffffffffffffffffffffff16602089015260808901516140d690613fc7908361545d565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b600081815260018301602052604081205480156141df57600061411a600183614a0f565b855490915060009061412e90600190614a0f565b905081811461419357600086600001828154811061414e5761414e614ec5565b906000526020600020015490508087600001848154811061417157614171614ec5565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806141a4576141a4615498565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612bf9565b6000915050612bf9565b6060612e9b8484600085856000808673ffffffffffffffffffffffffffffffffffffffff16858760405161421d91906149c4565b60006040518083038185875af1925050503d806000811461425a576040519150601f19603f3d011682016040523d82523d6000602084013e61425f565b606091505b50915091506142708783838761427b565b979650505050505050565b6060831561431157825160000361430a5773ffffffffffffffffffffffffffffffffffffffff85163b61430a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bab565b5081612e9b565b612e9b83838151156143265781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610bab91906152d9565b73ffffffffffffffffffffffffffffffffffffffff81168114612a8557600080fd5b6000806040838503121561438f57600080fd5b8235915060208301356143a18161435a565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610100810167ffffffffffffffff811182821017156143ff576143ff6143ac565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561444c5761444c6143ac565b604052919050565b600067ffffffffffffffff82111561446e5761446e6143ac565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f8301126144ab57600080fd5b81356144be6144b982614454565b614405565b8181528460208386010111156144d357600080fd5b816020850160208301376000918101602001919091529392505050565b6000806040838503121561450357600080fd5b82359150602083013567ffffffffffffffff81111561452157600080fd5b61452d8582860161449a565b9150509250929050565b60005b8381101561455257818101518382015260200161453a565b50506000910152565b60008151808452614573816020860160208601614537565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600a811061460b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b841515815260806020820152600061462a608083018661455b565b905061463960408301856145d4565b82606083015295945050505050565b60008083601f84011261465a57600080fd5b50813567ffffffffffffffff81111561467257600080fd5b60208301915083602082850101111561468a57600080fd5b9250929050565b6000806000604084860312156146a657600080fd5b83359250602084013567ffffffffffffffff8111156146c457600080fd5b6146d086828701614648565b9497909650939450505050565b6000602082840312156146ef57600080fd5b5035919050565b6000806040838503121561470957600080fd5b82356147148161435a565b946020939093013593505050565b60008060006060848603121561473757600080fd5b83356147428161435a565b925060208401356147528161435a565b929592945050506040919091013590565b871515815260e06020820152600061477e60e083018961455b565b905061478d60408301886145d4565b8560608301528460808301528360a08301528260c083015298975050505050505050565b600080604083850312156147c457600080fd5b8235915060208301356bffffffffffffffffffffffff811681146143a157600080fd5b63ffffffff81168114612a8557600080fd5b6000806040838503121561480c57600080fd5b8235915060208301356143a1816147e7565b600080828403606081121561483257600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561486657600080fd5b506020830190509250929050565b600067ffffffffffffffff82111561488e5761488e6143ac565b5060051b60200190565b600080600080606085870312156148ae57600080fd5b8435935060208086013567ffffffffffffffff808211156148ce57600080fd5b818801915088601f8301126148e257600080fd5b81356148f06144b982614874565b81815260059190911b8301840190848101908b83111561490f57600080fd5b8585015b838110156149475780358581111561492b5760008081fd5b6149398e89838a010161449a565b845250918601918601614913565b5097505050604088013592508083111561496057600080fd5b505061496e87828801614648565b95989497509550505050565b60006020828403121561498c57600080fd5b81356135de8161435a565b80516149a28161435a565b919050565b6000602082840312156149b957600080fd5b81516135de8161435a565b600082516149d6818460208701614537565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612bf957612bf96149e0565b805180151581146149a257600080fd5b600082601f830112614a4357600080fd5b8151614a516144b982614454565b818152846020838601011115614a6657600080fd5b612e9b826020830160208701614537565b60008060408385031215614a8a57600080fd5b614a9383614a22565b9150602083015167ffffffffffffffff811115614aaf57600080fd5b61452d85828601614a32565b600181811c90821680614acf57607f821691505b602082108103614b08577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f821115612df357600081815260208120601f850160051c81016020861015614b355750805b601f850160051c820191505b81811015614b5457828155600101614b41565b505050505050565b67ffffffffffffffff831115614b7457614b746143ac565b614b8883614b828354614abb565b83614b0e565b6000601f841160018114614bda5760008515614ba45750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355614c70565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b82811015614c295786850135825560209485019460019092019101614c09565b5086821015614c64577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612e9b602083018486614c77565b600060208284031215614ce657600080fd5b612bf682614a22565b600060208284031215614d0157600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115613d1e57613d1e6149e0565b80820180821115612bf957612bf96149e0565b62ffffff81168114612a8557600080fd5b8135614d5c816147e7565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135614d9c81614d40565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b604081018235614de7816147e7565b63ffffffff1682526020830135614dfd81614d40565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015614e84577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552614e7286835161455b565b95509382019390820190600101614e38565b505085840381870152505050614e9b818587614c77565b9695505050505050565b8181036000831280158383131683831282161715613d1e57613d1e6149e0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203614f2557614f256149e0565b5060010190565b805169ffffffffffffffffffff811681146149a257600080fd5b600080600080600060a08688031215614f5e57600080fd5b614f6786614f2c565b9450602086015193506040860151925060608601519150614f8a60808701614f2c565b90509295509295909350565b60ff8181168382160190811115612bf957612bf96149e0565b8082028115828204841417612bf957612bf96149e0565b60008060408385031215614fd957600080fd5b505080516020909101519092909150565b60008154614ff781614abb565b808552602060018381168015615014576001811461504c5761507a565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955061507a565b866000528260002060005b858110156150725781548a8201860152908301908401615057565b890184019650505b505050505092915050565b602081526000612bf66020830184614fea565b600082601f8301126150a957600080fd5b815160206150b96144b983614874565b82815260059290921b840181019181810190868411156150d857600080fd5b8286015b848110156150f357805183529183019183016150dc565b509695505050505050565b60006020828403121561511057600080fd5b815167ffffffffffffffff8082111561512857600080fd5b90830190610100828603121561513d57600080fd5b6151456143db565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261517d60a08401614997565b60a082015260c08301518281111561519457600080fd5b6151a087828601615098565b60c08301525060e0830151828111156151b857600080fd5b6151c487828601614a32565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015615203578151875295820195908201906001016151e7565b509495945050505050565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c084015161010080818501525061527f6101408401826151d3565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0848303016101208501526152bb828261455b565b91505082810360208401526152d08185614fea565b95945050505050565b602081526000612bf6602083018461455b565b828152604060208201526000612e9b604083018461455b565b6000806040838503121561531857600080fd5b61532183614a22565b9150602083015190509250929050565b600181815b8085111561538a57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615370576153706149e0565b8085161561537d57918102915b93841c9390800290615336565b509250929050565b6000826153a157506001612bf9565b816153ae57506000612bf9565b81600181146153c457600281146153ce576153ea565b6001915050612bf9565b60ff8411156153df576153df6149e0565b50506001821b612bf9565b5060208310610133831016604e8410600b841016171561540d575081810a612bf9565b6154178383615331565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615449576154496149e0565b029392505050565b6000612bf68383615392565b600082615493577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea164736f6c6343000813000a", } var AutomationRegistryLogicBABI = AutomationRegistryLogicBMetaData.ABI @@ -5280,7 +5281,7 @@ func (AutomationRegistryLogicBBillingConfigOverrideRemoved) Topic() common.Hash } func (AutomationRegistryLogicBBillingConfigSet) Topic() common.Hash { - return common.HexToHash("0x720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c") + return common.HexToHash("0xca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba3") } func (AutomationRegistryLogicBCancelledUpkeepReport) Topic() common.Hash { diff --git a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go index eeec869db65..d648604895b 100644 --- a/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go +++ b/core/gethwrappers/generated/automation_registry_wrapper_2_3/automation_registry_wrapper_2_3.go @@ -34,6 +34,7 @@ type AutomationRegistryBase23BillingConfig struct { GasFeePPB uint32 FlatFeeMilliCents *big.Int PriceFeed common.Address + Decimals uint8 FallbackPrice *big.Int MinSpend *big.Int } @@ -63,8 +64,8 @@ type AutomationRegistryBase23OnchainConfig struct { } var AutomationRegistryMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicA2_3\",\"name\":\"logicA\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"contractIERC20[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b50604051620061f0380380620061f083398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615abc620007346000396000818160be015261017101526000505060005050600050506000505060006137cc01526000505060008181610db101528181610ebf01528181610fea01528181611034015281816115820152612ef70152615abc6000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b806379ba5097116100a557806379ba5097146101b65780637bee169d146101cb57806381ff7048146101eb576100bc565b8063181f5a7714610103578063349e8cca14610162575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061014c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101599190614513565b60405180910390f35b34801561016e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610159565b3480156101c257600080fd5b50610101610356565b3480156101d757600080fd5b506101016101e6366004614a88565b610458565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610159565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610191565b34801561029c57600080fd5b506101016102ab366004614be9565b610d99565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610159565b34801561030257600080fd5b50610101610311366004614c8a565b6110b5565b34801561032257600080fd5b50610101610331366004614d41565b611396565b34801561034257600080fd5b50610101610351366004614e0e565b6113d0565b60015473ffffffffffffffffffffffffffffffffffffffff1633146103dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104606113e4565b601f8851111561049c576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036104d9576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806104f857506104f0866003614e61565b60ff16885111155b1561052f576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805182511461056a576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105748282611467565b61057e88886118cf565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ba89190614e7d565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610c1f91859174010000000000000000000000000000000000000000900416614e96565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610c509190614f04565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610cb5904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d611f90565b601355600960008181610cc882826143fa565b5050505060005b876101c0015151811015610d2257610d0f886101c001518281518110610cf757610cf761508a565b6020026020010151600961203a90919063ffffffff16565b5080610d1a816150b9565b915050610ccf565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610d859286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f906150f1565b60405180910390a150505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e08576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e42576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e5082840184615187565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610eab576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f2f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610f6e90859070010000000000000000000000000000000090046bffffffffffffffffffffffff166151a0565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016825260219052205461101d9085906151c5565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152919250611219576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611262576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a351461129e576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101516112ae9060016151d8565b60ff16861415806112bf5750858414155b156112f6576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113068a8a8a8a8a8a8a8a612065565b60006113128a8a6122ce565b905060208b0135600881901c63ffffffff1661132f848487612387565b836020015163ffffffff168163ffffffff16111561138757601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b6000806000858060200190518101906113af919061534b565b9250925092506113c58989898689898888610458565b505050505050505050565b6113d86113e4565b6113e181612f6d565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016103d3565b565b60005b60245481101561152557602260006024838154811061148b5761148b61508a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffff000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061151d816150b9565b91505061146a565b50611532602460006143fa565b60255460ff1660005b83518110156118c95760008482815181106115585761155861508a565b6020026020010151905060008483815181106115765761157661508a565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156115ec575060018460018111156115ea576115ea6154f6565b145b15611623576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061165e5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611695576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156116ff576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018082019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec40180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8581169182179092556000818152602260209081526040918290208651815488840180518a8701805163ffffffff9095167fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000909416841764010000000062ffffff93841602177fffffffffff0000000000000000000000000000000000000000ffffffffffffff16670100000000000000958b16959095029490941785556060808c0180519b87019b909b556080808d018051600290980180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff998a1617905589519586529351909216968401969096529251909716948101949094529551918301919091529251909216928201929092527f720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c9060a00160405180910390a2505080806118c1906150b9565b91505061153b565b50505050565b60005b600e5481101561194657611933600e82815481106118f2576118f261508a565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff90911690613062565b508061193e816150b9565b9150506118d2565b5060255460009060ff16815b600e54811015611ab757600e818154811061196f5761196f61508a565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c9291849081106119ac576119ac61508a565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611a4e57611a4e6154f6565b148015611a93575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611aa557611aa3600f8461203a565b505b80611aaf816150b9565b915050611952565b50611ac4600d60006143fa565b611ad0600e60006143fa565b6040805160808101825260008082526020820181905291810182905260608101829052905b8551811015611f6057600c6000878381518110611b1457611b1461508a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611b7f576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611ba957611ba961508a565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611bfe576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611c2f57611c2f61508a565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611cd757611cd761508a565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611d47576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611e02576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115611f3c57611f3c6154f6565b03611f4e57611f4c600f8561326a565b505b80611f58816150b9565b915050611af5565b508451611f7490600d906020880190614418565b508351611f8890600e906020870190614418565b505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001611fb499989796959493929190615525565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b600061205c8373ffffffffffffffffffffffffffffffffffffffff841661328c565b90505b92915050565b600087876040516120779291906155ba565b60405190819003812061208e918b906020016155ca565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b88811015612265576001858783602081106120fa576120fa61508a565b61210791901a601b6151d8565b8c8c858181106121195761211961508a565b905060200201358b8b868181106121325761213261508a565b905060200201356040516000815260200160405260405161216f949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612191573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff808216151580855261010090920416938301939093529095509350905061223f576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061225d906150b9565b9150506120dd565b50827e010101010101010101010101010101010101010101010101010101010101018416146122c0576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6123076040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b6000612315838501856156bb565b604081015151606082015151919250908114158061233857508082608001515114155b806123485750808260a001515114155b1561237f576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff8111156123a7576123a7614526565b60405190808252806020026020018201604052801561247357816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816123c55790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125359190614e7d565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612589573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125ad9190614e7d565b905060005b866040015151811015612a3d5760046000886040015183815181106125d9576125d961508a565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106126fc576126fc61508a565b602002602001015160000181905250612731876040015182815181106127245761272461508a565b60200260200101516132db565b8582815181106127435761274361508a565b6020026020010151606001906001811115612760576127606154f6565b90816001811115612773576127736154f6565b815250506127d7876040015182815181106127905761279061508a565b602002602001015184896080015184815181106127af576127af61508a565b60200260200101518885815181106127c9576127c961508a565b60200260200101518c613386565b8683815181106127e9576127e961508a565b60200260200101516020018784815181106128065761280661508a565b602002602001015160c00182815250821515151581525050508481815181106128315761283161508a565b602002602001015160200151156128615760018460000181815161285591906157a8565b61ffff16905250612866565b612a2b565b6128cc85828151811061287b5761287b61508a565b60200260200101516000015160800151886060015183815181106128a1576128a161508a565b60200260200101518960a0015184815181106128bf576128bf61508a565b60200260200101516134a5565b8683815181106128de576128de61508a565b60200260200101516040018784815181106128fb576128fb61508a565b602002602001015160800182815250821515151581525050508760800151600161292591906151d8565b6129339060ff1660406157c3565b6103a48860a00151838151811061294c5761294c61508a565b60200260200101515161295f91906151c5565b61296991906151c5565b85828151811061297b5761297b61508a565b602002602001015160a001818152505084818151811061299d5761299d61508a565b602002602001015160a00151846060018181516129ba91906151c5565b90525084518590829081106129d1576129d161508a565b602002602001015160800151866129e891906157da565b9550612a2b87604001518281518110612a0357612a0361508a565b602002602001015184878481518110612a1e57612a1e61508a565b60200260200101516136c0565b80612a35816150b9565b9150506125b2565b50825161ffff16600003612a545750505050505050565b61c738612a623660106157c3565b5a612a6d90886157da565b612a7791906151c5565b612a8191906151c5565b835190955061232890612a989061ffff168761581c565b612aa291906151c5565b60408051606081018252600080825260208201819052918101829052919650612aca896137c5565b905060005b886040015151811015612e0657868181518110612aee57612aee61508a565b60200260200101516020015115612df457801580612b86575086612b136001836157da565b81518110612b2357612b2361508a565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612b5c57612b5c61508a565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612bba57612bb78a888381518110612ba157612ba161508a565b60200260200101516000015161010001516138b6565b92505b6000612cd88b6040518061012001604052808b8681518110612bde57612bde61508a565b60200260200101516080015181526020018c81526020018a606001518c8781518110612c0c57612c0c61508a565b602002602001015160a001518a612c2391906157c3565b612c2d919061581c565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612c5e57612c5e61508a565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612cad57612cad61508a565b60200260200101518b8681518110612cc757612cc761508a565b602002602001015160000151613a07565b9050806060015187604001818151612cf091906151a0565b6bffffffffffffffffffffffff169052506040810151602088018051612d179083906151a0565b6bffffffffffffffffffffffff169052508751889083908110612d3c57612d3c61508a565b60200260200101516040015115158a604001518381518110612d6057612d6061508a565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612d9d91906151a0565b8b8681518110612daf57612daf61508a565b6020026020010151608001518d8f608001518881518110612dd257612dd261508a565b6020026020010151604051612dea9493929190615830565b60405180910390a3505b80612dfe816150b9565b915050612acf565b505050602083810151336000908152600b90925260409091208054600290612e439084906201000090046bffffffffffffffffffffffff166151a0565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff16612ea191906151a0565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555082604001518360200151612ee391906151a0565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254612f5f91906151c5565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603612fec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016103d3565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e010000000000000000000000000000900490911660608201529061325e5760008160600151856130fa919061586d565b905060006131088583615892565b9050808360400181815161311c91906151a0565b6bffffffffffffffffffffffff1690525061313785826158bd565b8360600181815161314891906151a0565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b600061205c8373ffffffffffffffffffffffffffffffffffffffff8416613d03565b60008181526001830160205260408120546132d35750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561205f565b50600061205f565b6000818160045b600f811015613368577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106133205761332061508a565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461335657506000949350505050565b80613360816150b9565b9150506132e2565b5081600f1a600181111561337e5761337e6154f6565b949350505050565b6000808080856060015160018111156133a1576133a16154f6565b036133c7576133b38888888888613df6565b6133c25760009250905061349b565b61343f565b6001856060015160018111156133df576133df6154f6565b0361340d5760006133f289898988613f80565b9250905080613407575060009250905061349b565b5061343f565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061349457877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516134819190614513565b60405180910390a260009250905061349b565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff1615613502576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b0000000000000000000000000000000000000000000000000000000090613577908590602401614513565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061364a90879087906004016158ed565b60408051808303816000875af1158015613668573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061368c9190615906565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b6000816060015160018111156136d8576136d86154f6565b0361373c57600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b600181606001516001811115613754576137546154f6565b036137c05760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613835573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613859919061594e565b5093505092505060008213158061386f57508042105b8061389f57506000846040015162ffffff1611801561389f575061389381426157da565b846040015162ffffff16105b156138af575050601b5492915050565b5092915050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa158015613978573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061399c919061594e565b509350509250506000821315806139b257508042105b806139e257506000866040015162ffffff161180156139e257506139d681426157da565b866040015162ffffff16105b156139f657600183015460408501526139fe565b604084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613a805760008381526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845260e088018051919091529251925192169101525b6000613a8c868661418d565b60c0840151602082015182519293509091600091613aa9916151a0565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613b2e57819050613b0f87608001518860e0015160400151846bffffffffffffffffffffffff16613b0091906157c3565b613b0a919061581c565b614358565b6bffffffffffffffffffffffff16604084015260006060840152613bba565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613bba57819050613ba683604001516bffffffffffffffffffffffff1688608001518960e0015160400151856bffffffffffffffffffffffff16613b9291906157c3565b613b9c919061581c565b613b0a91906157da565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613c0090849070010000000000000000000000000000000090046bffffffffffffffffffffffff1661586d565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613c5b9084906fffffffffffffffffffffffffffffffff1661599e565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613cf291906157da565b909155509298975050505050505050565b60008181526001830160205260408120548015613dec576000613d276001836157da565b8554909150600090613d3b906001906157da565b9050818114613da0576000866000018281548110613d5b57613d5b61508a565b9060005260206000200154905080876000018481548110613d7e57613d7e61508a565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613db157613db16159c7565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061205f565b600091505061205f565b60008084806020019051810190613e0d91906159f6565b845160e00151815191925063ffffffff90811691161015613e6a57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613e589190614513565b60405180910390a26000915050613f77565b8260e001518015613f2a5750602081015115801590613f2a5750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015613f03573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f279190614e7d565b14155b80613f3c5750805163ffffffff168611155b15613f7157867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613e589190614513565b60019150505b95945050505050565b600080600084806020019051810190613f999190615a4e565b9050600087826000015183602001518460400151604051602001613ffb94939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156140d657506080820151158015906140d65750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156140af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140d39190614e7d565b14155b806140eb575086826060015163ffffffff1610155b1561413557877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516141209190614513565b60405180910390a26000935091506141849050565b60008181526008602052604090205460ff161561417c57877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516141209190614513565b600193509150505b94509492505050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff1683606001516141cb91906157c3565b905082610100015180156141de5750803a105b156141e657503a5b60008360a0015184604001518560200151866000015161420691906151c5565b61421090856157c3565b61421a91906151c5565b61422491906157c3565b905061423d8460e001516040015182613b0a919061581c565b6bffffffffffffffffffffffff168352608084015161426090613b0a908361581c565b6bffffffffffffffffffffffff16604084015260e0840151602001516000906142979062ffffff16683635c9adc5dea000006157c3565b9050600081633b9aca008760a001518860e001516000015163ffffffff1689604001518a60000151896142ca91906157c3565b6142d491906151c5565b6142de91906157c3565b6142e891906157c3565b6142f2919061581c565b6142fc91906151c5565b90506143158660e001516040015182613b0a919061581c565b6bffffffffffffffffffffffff166020860152608086015161433b90613b0a908361581c565b6bffffffffffffffffffffffff1660608601525050505092915050565b60006bffffffffffffffffffffffff8211156143f6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016103d3565b5090565b50805460008255906000526020600020908101906113e1919061449a565b828054828255906000526020600020908101928215614492579160200282015b8281111561449257825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614438565b506143f69291505b5b808211156143f6576000815560010161449b565b6000815180845260005b818110156144d5576020818501810151868301820152016144b9565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061205c60208301846144af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561457957614579614526565b60405290565b60405160a0810167ffffffffffffffff8111828210171561457957614579614526565b60405160c0810167ffffffffffffffff8111828210171561457957614579614526565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561460c5761460c614526565b604052919050565b600067ffffffffffffffff82111561462e5761462e614526565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146113e157600080fd5b803561466581614638565b919050565b600082601f83011261467b57600080fd5b8135602061469061468b83614614565b6145c5565b82815260059290921b840181019181810190868411156146af57600080fd5b8286015b848110156146d35780356146c681614638565b83529183019183016146b3565b509695505050505050565b803560ff8116811461466557600080fd5b63ffffffff811681146113e157600080fd5b8035614665816146ef565b80151581146113e157600080fd5b80356146658161470c565b62ffffff811681146113e157600080fd5b803561466581614725565b61ffff811681146113e157600080fd5b803561466581614741565b6000610200828403121561476f57600080fd5b614777614555565b905061478282614701565b815261479060208301614701565b60208201526147a160408301614701565b60408201526147b26060830161465a565b60608201526147c36080830161471a565b60808201526147d460a08301614736565b60a08201526147e560c08301614701565b60c08201526147f660e08301614701565b60e082015261010061480981840161465a565b9082015261012061481b838201614751565b9082015261014061482d83820161465a565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff81111561486e57600080fd5b61487a8582860161466a565b8284015250506101e061488e81840161465a565b9082015292915050565b803567ffffffffffffffff8116811461466557600080fd5b600082601f8301126148c157600080fd5b813567ffffffffffffffff8111156148db576148db614526565b61490c60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016145c5565b81815284602083860101111561492157600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261494f57600080fd5b8135602061495f61468b83614614565b82815260059290921b8401810191818101908684111561497e57600080fd5b8286015b848110156146d357803561499581614638565b8352918301918301614982565b6bffffffffffffffffffffffff811681146113e157600080fd5b600082601f8301126149cd57600080fd5b813560206149dd61468b83614614565b82815260a092830285018201928282019190878511156149fc57600080fd5b8387015b85811015614a7b5781818a031215614a185760008081fd5b614a2061457f565b8135614a2b816146ef565b815281860135614a3a81614725565b81870152604082810135614a4d81614638565b9082015260608281013590820152608080830135614a6a816149a2565b908201528452928401928101614a00565b5090979650505050505050565b600080600080600080600080610100898b031215614aa557600080fd5b883567ffffffffffffffff80821115614abd57600080fd5b614ac98c838d0161466a565b995060208b0135915080821115614adf57600080fd5b614aeb8c838d0161466a565b9850614af960408c016146de565b975060608b0135915080821115614b0f57600080fd5b614b1b8c838d0161475c565b9650614b2960808c01614898565b955060a08b0135915080821115614b3f57600080fd5b614b4b8c838d016148b0565b945060c08b0135915080821115614b6157600080fd5b614b6d8c838d0161493e565b935060e08b0135915080821115614b8357600080fd5b50614b908b828c016149bc565b9150509295985092959890939650565b60008083601f840112614bb257600080fd5b50813567ffffffffffffffff811115614bca57600080fd5b602083019150836020828501011115614be257600080fd5b9250929050565b60008060008060608587031215614bff57600080fd5b8435614c0a81614638565b935060208501359250604085013567ffffffffffffffff811115614c2d57600080fd5b614c3987828801614ba0565b95989497509550505050565b60008083601f840112614c5757600080fd5b50813567ffffffffffffffff811115614c6f57600080fd5b6020830191508360208260051b8501011115614be257600080fd5b60008060008060008060008060e0898b031215614ca657600080fd5b606089018a811115614cb757600080fd5b8998503567ffffffffffffffff80821115614cd157600080fd5b614cdd8c838d01614ba0565b909950975060808b0135915080821115614cf657600080fd5b614d028c838d01614c45565b909750955060a08b0135915080821115614d1b57600080fd5b50614d288b828c01614c45565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614d5a57600080fd5b863567ffffffffffffffff80821115614d7257600080fd5b614d7e8a838b0161466a565b97506020890135915080821115614d9457600080fd5b614da08a838b0161466a565b9650614dae60408a016146de565b95506060890135915080821115614dc457600080fd5b614dd08a838b016148b0565b9450614dde60808a01614898565b935060a0890135915080821115614df457600080fd5b50614e0189828a016148b0565b9150509295509295509295565b600060208284031215614e2057600080fd5b8135614e2b81614638565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff81811683821602908116908181146138af576138af614e32565b600060208284031215614e8f57600080fd5b5051919050565b63ffffffff8181168382160190808211156138af576138af614e32565b600081518084526020808501945080840160005b83811015614ef957815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101614ec7565b509495945050505050565b60208152614f1b60208201835163ffffffff169052565b60006020830151614f34604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e0830151610100614fb38185018363ffffffff169052565b8401519050610120614fdc8482018373ffffffffffffffffffffffffffffffffffffffff169052565b8401519050610140614ff38482018361ffff169052565b840151905061016061501c8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e080860182905291925090615064610220860184614eb3565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036150ea576150ea614e32565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526151218184018a614eb3565b905082810360808401526151358189614eb3565b905060ff871660a084015282810360c084015261515281876144af565b905067ffffffffffffffff851660e084015282810361010084015261517781856144af565b9c9b505050505050505050505050565b60006020828403121561519957600080fd5b5035919050565b6bffffffffffffffffffffffff8181168382160190808211156138af576138af614e32565b8082018082111561205f5761205f614e32565b60ff818116838216019081111561205f5761205f614e32565b8051614665816146ef565b805161466581614638565b80516146658161470c565b805161466581614725565b805161466581614741565b600082601f83011261523957600080fd5b8151602061524961468b83614614565b82815260059290921b8401810191818101908684111561526857600080fd5b8286015b848110156146d357805161527f81614638565b835291830191830161526c565b600082601f83011261529d57600080fd5b815160206152ad61468b83614614565b82815260a092830285018201928282019190878511156152cc57600080fd5b8387015b85811015614a7b5781818a0312156152e85760008081fd5b6152f061457f565b81516152fb816146ef565b81528186015161530a81614725565b8187015260408281015161531d81614638565b908201526060828101519082015260808083015161533a816149a2565b9082015284529284019281016152d0565b60008060006060848603121561536057600080fd5b835167ffffffffffffffff8082111561537857600080fd5b90850190610200828803121561538d57600080fd5b615395614555565b61539e836151f1565b81526153ac602084016151f1565b60208201526153bd604084016151f1565b60408201526153ce606084016151fc565b60608201526153df60808401615207565b60808201526153f060a08401615212565b60a082015261540160c084016151f1565b60c082015261541260e084016151f1565b60e08201526101006154258185016151fc565b9082015261012061543784820161521d565b908201526101406154498482016151fc565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561548257600080fd5b61548e8a828701615228565b8284015250506101e06154a28185016151fc565b9082015260208701519095509150808211156154bd57600080fd5b6154c987838801615228565b935060408601519150808211156154df57600080fd5b506154ec8682870161528c565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b16604085015281606085015261556c8285018b614eb3565b91508382036080850152615580828a614eb3565b915060ff881660a085015283820360c085015261559d82886144af565b90861660e0850152838103610100850152905061517781856144af565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f8301126155f157600080fd5b8135602061560161468b83614614565b82815260059290921b8401810191818101908684111561562057600080fd5b8286015b848110156146d35780358352918301918301615624565b600082601f83011261564c57600080fd5b8135602061565c61468b83614614565b82815260059290921b8401810191818101908684111561567b57600080fd5b8286015b848110156146d357803567ffffffffffffffff81111561569f5760008081fd5b6156ad8986838b01016148b0565b84525091830191830161567f565b6000602082840312156156cd57600080fd5b813567ffffffffffffffff808211156156e557600080fd5b9083019060c082860312156156f957600080fd5b6157016145a2565b823581526020830135602082015260408301358281111561572157600080fd5b61572d878286016155e0565b60408301525060608301358281111561574557600080fd5b615751878286016155e0565b60608301525060808301358281111561576957600080fd5b6157758782860161563b565b60808301525060a08301358281111561578d57600080fd5b6157998782860161563b565b60a08301525095945050505050565b61ffff8181168382160190808211156138af576138af614e32565b808202811582820484141761205f5761205f614e32565b8181038181111561205f5761205f614e32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261582b5761582b6157ed565b500490565b6bffffffffffffffffffffffff8516815283602082015282604082015260806060820152600061586360808301846144af565b9695505050505050565b6bffffffffffffffffffffffff8281168282160390808211156138af576138af614e32565b60006bffffffffffffffffffffffff808416806158b1576158b16157ed565b92169190910492915050565b6bffffffffffffffffffffffff8181168382160280821691908281146158e5576158e5614e32565b505092915050565b82815260406020820152600061337e60408301846144af565b6000806040838503121561591957600080fd5b82516159248161470c565b6020939093015192949293505050565b805169ffffffffffffffffffff8116811461466557600080fd5b600080600080600060a0868803121561596657600080fd5b61596f86615934565b945060208601519350604086015192506060860151915061599260808701615934565b90509295509295909350565b6fffffffffffffffffffffffffffffffff8181168382160190808211156138af576138af614e32565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215615a0857600080fd5b6040516040810181811067ffffffffffffffff82111715615a2b57615a2b614526565b6040528251615a39816146ef565b81526020928301519281019290925250919050565b600060a08284031215615a6057600080fd5b615a6861457f565b82518152602083015160208201526040830151615a84816146ef565b60408201526060830151615a97816146ef565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"contractAutomationRegistryLogicA2_3\",\"name\":\"logicA\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contractIERC20Metadata\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"contractIChainModule\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"contractIERC20Metadata[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x6101806040523480156200001257600080fd5b50604051620065e2380380620065e283398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615eae620007346000396000818160be015261019101526000505060005050600050506000505060006139a301526000505060008181610db101528181610ebf01528181610fea01528181611034015281816116b601526130ce0152615eae6000f3fe6080604052600436106100bc5760003560e01c80638da5cb5b11610074578063b1dc65a41161004e578063b1dc65a4146102f6578063e3d0e71214610316578063f2fde38b14610336576100bc565b80638da5cb5b14610265578063a4c0ed3614610290578063afcb95d7146102b0576100bc565b8063349e8cca116100a5578063349e8cca1461018257806379ba5097146101d657806381ff7048146101eb576100bc565b80630870d3a114610103578063181f5a7714610123575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156100fc573d6000f35b3d6000fd5b005b34801561010f57600080fd5b5061010161011e366004614c23565b610356565b34801561012f57600080fd5b5061016c6040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b6040516101799190614d9f565b60405180910390f35b34801561018e57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610179565b3480156101e257600080fd5b50610101610c97565b3480156101f757600080fd5b5061024260175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610179565b34801561027157600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166101b1565b34801561029c57600080fd5b506101016102ab366004614dfb565b610d99565b3480156102bc57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610179565b34801561030257600080fd5b50610101610311366004614e9c565b6110b5565b34801561032257600080fd5b50610101610331366004614f53565b611396565b34801561034257600080fd5b50610101610351366004615020565b6113d0565b61035e6113e4565b601f8851111561039a576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff166000036103d7576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b865188511415806103f657506103ee866003615073565b60ff16885111155b1561042d576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8051825114610468576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6104728282611467565b61047c8888611a9f565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a82573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aa6919061508f565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610b1d918591740100000000000000000000000000000000000000009004166150a8565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610b4e9190615116565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610bb3904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d612160565b601355600960008181610bc68282614677565b5050505060005b876101c0015151811015610c2057610c0d886101c001518281518110610bf557610bf561529c565b6020026020010151600961220a90919063ffffffff16565b5080610c18816152cb565b915050610bcd565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610c839286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f90615303565b60405180910390a150505050505050505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610d1d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e08576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e42576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e5082840184615399565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610eab576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f2f576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610f6e90859070010000000000000000000000000000000090046bffffffffffffffffffffffff166153b2565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016825260219052205461101d9085906153d7565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152919250611219576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff16611262576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a351461129e576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60808101516112ae9060016153ea565b60ff16861415806112bf5750858414155b156112f6576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6113068a8a8a8a8a8a8a8a612235565b60006113128a8a61249e565b905060208b0135600881901c63ffffffff1661132f848487612557565b836020015163ffffffff168163ffffffff16111561138757601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b6000806000858060200190518101906113af91906155d4565b9250925092506113c58989898689898888610356565b505050505050505050565b6113d86113e4565b6113e181613144565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611465576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610d14565b565b60005b60245481101561152557602260006024838154811061148b5761148b61529c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffff00000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061151d816152cb565b91505061146a565b5061153260246000614677565b60255460ff1660005b8351811015611a995760008482815181106115585761155861529c565b6020026020010151905060008483815181106115765761157661529c565b602002602001015190508173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115ef919061577f565b60ff16816060015160ff1614158061167d5750806040015173ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015611651573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611675919061577f565b60ff16600814155b156116b4576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156117205750600184600181111561171e5761171e61579c565b145b15611757576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff821615806117925750604081015173ffffffffffffffffffffffffffffffffffffffff16155b156117c9576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82811660009081526022602052604090205467010000000000000090041615611833576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018181019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec401805473ffffffffffffffffffffffffffffffffffffffff8086167fffffffffffffffffffffffff0000000000000000000000000000000000000000909216821790925560008181526022602090815260409182902086518154928801518489015160608a015160ff167b01000000000000000000000000000000000000000000000000000000027fffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffff9190981667010000000000000002167fffffffff000000000000000000000000000000000000000000ffffffffffffff62ffffff909216640100000000027fffffffffffffffffffffffffffffffffffffffffffffffffff0000000000000090951663ffffffff9093169290921793909317929092169190911793909317835560808501519383019390935560a0840151600290920180546bffffffffffffffffffffffff9093167fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009093169290921790915590517fca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba390611a7c908490600060c08201905063ffffffff835116825262ffffff602084015116602083015273ffffffffffffffffffffffffffffffffffffffff604084015116604083015260ff6060840151166060830152608083015160808301526bffffffffffffffffffffffff60a08401511660a083015292915050565b60405180910390a250508080611a91906152cb565b91505061153b565b50505050565b60005b600e54811015611b1657611b03600e8281548110611ac257611ac261529c565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff90911690613239565b5080611b0e816152cb565b915050611aa2565b5060255460009060ff16815b600e54811015611c8757600e8181548110611b3f57611b3f61529c565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611b7c57611b7c61529c565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611c1e57611c1e61579c565b148015611c63575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611c7557611c73600f8461220a565b505b80611c7f816152cb565b915050611b22565b50611c94600d6000614677565b611ca0600e6000614677565b6040805160808101825260008082526020820181905291810182905260608101829052905b855181101561213057600c6000878381518110611ce457611ce461529c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611d4f576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611d7957611d7961529c565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611dce576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611dff57611dff61529c565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611ea757611ea761529c565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611f17576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611fd2576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905583600181111561210c5761210c61579c565b0361211e5761211c600f85613441565b505b80612128816152cb565b915050611cc5565b50845161214490600d906020880190614695565b50835161215890600e906020870190614695565b505050505050565b6000808a8a8a8a8a8a8a8a8a604051602001612184999897969594939291906157cb565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b600061222c8373ffffffffffffffffffffffffffffffffffffffff8416613463565b90505b92915050565b60008787604051612247929190615860565b60405190819003812061225e918b90602001615870565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b88811015612435576001858783602081106122ca576122ca61529c565b6122d791901a601b6153ea565b8c8c858181106122e9576122e961529c565b905060200201358b8b868181106123025761230261529c565b905060200201356040516000815260200160405260405161233f949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612361573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff808216151580855261010090920416938301939093529095509350905061240f576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b84019350808061242d906152cb565b9150506122ad565b50827e01010101010101010101010101010101010101010101010101010101010101841614612490576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b6124d76040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b60006124e583850185615961565b604081015151606082015151919250908114158061250857508082608001515114155b806125185750808260a001515114155b1561254f576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff8111156125775761257761472c565b60405190808252806020026020018201604052801561264357816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9092019101816125955790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126e1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612705919061508f565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612759573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061277d919061508f565b905060005b866040015151811015612c0d5760046000886040015183815181106127a9576127a961529c565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169181019190915285518690839081106128cc576128cc61529c565b602002602001015160000181905250612901876040015182815181106128f4576128f461529c565b60200260200101516134b2565b8582815181106129135761291361529c565b60200260200101516060019060018111156129305761293061579c565b908160018111156129435761294361579c565b815250506129a7876040015182815181106129605761296061529c565b6020026020010151848960800151848151811061297f5761297f61529c565b60200260200101518885815181106129995761299961529c565b60200260200101518c61355d565b8683815181106129b9576129b961529c565b60200260200101516020018784815181106129d6576129d661529c565b602002602001015160c0018281525082151515158152505050848181518110612a0157612a0161529c565b60200260200101516020015115612a3157600184600001818151612a259190615a4e565b61ffff16905250612a36565b612bfb565b612a9c858281518110612a4b57612a4b61529c565b6020026020010151600001516080015188606001518381518110612a7157612a7161529c565b60200260200101518960a001518481518110612a8f57612a8f61529c565b602002602001015161367c565b868381518110612aae57612aae61529c565b6020026020010151604001878481518110612acb57612acb61529c565b6020026020010151608001828152508215151515815250505087608001516001612af591906153ea565b612b039060ff166040615a69565b6103a48860a001518381518110612b1c57612b1c61529c565b602002602001015151612b2f91906153d7565b612b3991906153d7565b858281518110612b4b57612b4b61529c565b602002602001015160a0018181525050848181518110612b6d57612b6d61529c565b602002602001015160a0015184606001818151612b8a91906153d7565b9052508451859082908110612ba157612ba161529c565b60200260200101516080015186612bb89190615a80565b9550612bfb87604001518281518110612bd357612bd361529c565b602002602001015184878481518110612bee57612bee61529c565b6020026020010151613897565b80612c05816152cb565b915050612782565b50825161ffff16600003612c245750505050505050565b61c800612c32366010615a69565b5a612c3d9088615a80565b612c4791906153d7565b612c5191906153d7565b83519095506123f090612c689061ffff1687615ac2565b612c7291906153d7565b6040805160808101825260008082526020820181905291810182905260608101829052919650612ca18961399c565b905060005b886040015151811015612fdd57868181518110612cc557612cc561529c565b60200260200101516020015115612fcb57801580612d5d575086612cea600183615a80565b81518110612cfa57612cfa61529c565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612d3357612d3361529c565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15612d9157612d8e8a888381518110612d7857612d7861529c565b6020026020010151600001516101000151613a8d565b92505b6000612eaf8b6040518061012001604052808b8681518110612db557612db561529c565b60200260200101516080015181526020018c81526020018a606001518c8781518110612de357612de361529c565b602002602001015160a001518a612dfa9190615a69565b612e049190615ac2565b81526020018d6000015181526020018d6020015181526020018681526020018b8681518110612e3557612e3561529c565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c604001518581518110612e8457612e8461529c565b60200260200101518b8681518110612e9e57612e9e61529c565b602002602001015160000151613c09565b9050806060015187604001818151612ec791906153b2565b6bffffffffffffffffffffffff169052506040810151602088018051612eee9083906153b2565b6bffffffffffffffffffffffff169052508751889083908110612f1357612f1361529c565b60200260200101516040015115158a604001518381518110612f3757612f3761529c565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b83606001518460400151612f7491906153b2565b8b8681518110612f8657612f8661529c565b6020026020010151608001518d8f608001518881518110612fa957612fa961529c565b6020026020010151604051612fc19493929190615ad6565b60405180910390a3505b80612fd5816152cb565b915050612ca6565b505050602083810151336000908152600b9092526040909120805460029061301a9084906201000090046bffffffffffffffffffffffff166153b2565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff1661307891906153b2565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550826040015183602001516130ba91906153b2565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461313691906153d7565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff8216036131c3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610d14565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906134355760008160600151856132d19190615b13565b905060006132df8583615b38565b905080836040018181516132f391906153b2565b6bffffffffffffffffffffffff1690525061330e8582615b63565b8360600181815161331f91906153b2565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b600061222c8373ffffffffffffffffffffffffffffffffffffffff8416613f05565b60008181526001830160205260408120546134aa5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561222f565b50600061222f565b6000818160045b600f81101561353f577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106134f7576134f761529c565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161461352d57506000949350505050565b80613537816152cb565b9150506134b9565b5081600f1a60018111156135555761355561579c565b949350505050565b6000808080856060015160018111156135785761357861579c565b0361359e5761358a8888888888613ff8565b61359957600092509050613672565b613616565b6001856060015160018111156135b6576135b661579c565b036135e45760006135c989898988614182565b92509050806135de5750600092509050613672565b50613616565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061366b57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516136589190614d9f565b60405180910390a2600092509050613672565b6001925090505b9550959350505050565b601454600090819077010000000000000000000000000000000000000000000000900460ff16156136d9576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061374e908590602401614d9f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906138219087908790600401615b93565b60408051808303816000875af115801561383f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138639190615bac565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b6000816060015160018111156138af576138af61579c565b0361391357600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b60018160600151600181111561392b5761392b61579c565b036139975760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613a0c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a309190615bf4565b50935050925050600082131580613a4657508042105b80613a7657506000846040015162ffffff16118015613a765750613a6a8142615a80565b846040015162ffffff16105b15613a86575050601b5492915050565b5092915050565b60408051608081018252600080825260208083018281528385018381526060850184905273ffffffffffffffffffffffffffffffffffffffff878116855260229093528584208054640100000000810462ffffff1690925263ffffffff82169092527b01000000000000000000000000000000000000000000000000000000810460ff16855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495919484936701000000000000009092049091169163feaf968c9160048083019260a09291908290030181865afa158015613b7a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b9e9190615bf4565b50935050925050600082131580613bb457508042105b80613be457506000866040015162ffffff16118015613be45750613bd88142615a80565b866040015162ffffff16105b15613bf85760018301546060850152613c00565b606084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613c825760008381526023602090815260409182902082518084018452905463ffffffff811680835262ffffff640100000000909204821692840192835260e089018051909401529051915191169101525b6000613c8e868661438f565b60c0840151602082015182519293509091600091613cab916153b2565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613d3057819050613d1187608001518860e0015160600151846bffffffffffffffffffffffff16613d029190615a69565b613d0c9190615ac2565b6145d5565b6bffffffffffffffffffffffff16604084015260006060840152613dbc565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613dbc57819050613da883604001516bffffffffffffffffffffffff1688608001518960e0015160600151856bffffffffffffffffffffffff16613d949190615a69565b613d9e9190615ac2565b613d0c9190615a80565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613e0290849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615b13565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613e5d9084906fffffffffffffffffffffffffffffffff16615c44565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613ef49190615a80565b909155509298975050505050505050565b60008181526001830160205260408120548015613fee576000613f29600183615a80565b8554909150600090613f3d90600190615a80565b9050818114613fa2576000866000018281548110613f5d57613f5d61529c565b9060005260206000200154905080876000018481548110613f8057613f8061529c565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613fb357613fb3615c6d565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061222f565b600091505061222f565b6000808480602001905181019061400f9190615c9c565b845160e00151815191925063ffffffff9081169116101561406c57867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88660405161405a9190614d9f565b60405180910390a26000915050614179565b8260e00151801561412c575060208101511580159061412c5750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614105573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614129919061508f565b14155b8061413e5750805163ffffffff168611155b1561417357867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018660405161405a9190614d9f565b60019150505b95945050505050565b60008060008480602001905181019061419b9190615cf4565b90506000878260000151836020015184604001516040516020016141fd94939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156142d857506080820151158015906142d85750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156142b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142d5919061508f565b14155b806142ed575086826060015163ffffffff1610155b1561433757877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301876040516143229190614d9f565b60405180910390a26000935091506143869050565b60008181526008602052604090205460ff161561437e57877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8876040516143229190614d9f565b600193509150505b94509492505050565b60408051608081018252600080825260208201819052918101829052606081019190915260008260e001516000015160ff1690506000846060015161ffff1684606001516143dd9190615a69565b905083610100015180156143f05750803a105b156143f857503a5b60006012831161440957600161441f565b614414601284615a80565b61441f90600a615e95565b9050600060128410614432576001614448565b61443d846012615a80565b61444890600a615e95565b905060008660a0015187604001518860200151896000015161446a91906153d7565b6144749087615a69565b61447e91906153d7565b6144889190615a69565b90506144ab828860e00151606001516144a19190615a69565b613d028584615a69565b6bffffffffffffffffffffffff16865260808701516144ce90613d0c9083615ac2565b6bffffffffffffffffffffffff1660408088019190915260e088015101516000906145079062ffffff16683635c9adc5dea00000615a69565b9050600081633b9aca008a60a001518b60e001516020015163ffffffff168c604001518d600001518b61453a9190615a69565b61454491906153d7565b61454e9190615a69565b6145589190615a69565b6145629190615ac2565b61456c91906153d7565b905061458f848a60e00151606001516145859190615a69565b613d028784615a69565b6bffffffffffffffffffffffff16602089015260808901516145b590613d0c9083615ac2565b6bffffffffffffffffffffffff1660608901525050505050505092915050565b60006bffffffffffffffffffffffff821115614673576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610d14565b5090565b50805460008255906000526020600020908101906113e19190614717565b82805482825590600052602060002090810192821561470f579160200282015b8281111561470f57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff9091161782556020909201916001909101906146b5565b506146739291505b5b808211156146735760008155600101614718565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561477f5761477f61472c565b60405290565b60405160c0810167ffffffffffffffff8111828210171561477f5761477f61472c565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156147ef576147ef61472c565b604052919050565b600067ffffffffffffffff8211156148115761481161472c565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146113e157600080fd5b80356148488161481b565b919050565b600082601f83011261485e57600080fd5b8135602061487361486e836147f7565b6147a8565b82815260059290921b8401810191818101908684111561489257600080fd5b8286015b848110156148b65780356148a98161481b565b8352918301918301614896565b509695505050505050565b60ff811681146113e157600080fd5b8035614848816148c1565b63ffffffff811681146113e157600080fd5b8035614848816148db565b80151581146113e157600080fd5b8035614848816148f8565b62ffffff811681146113e157600080fd5b803561484881614911565b61ffff811681146113e157600080fd5b80356148488161492d565b6000610200828403121561495b57600080fd5b61496361475b565b905061496e826148ed565b815261497c602083016148ed565b602082015261498d604083016148ed565b604082015261499e6060830161483d565b60608201526149af60808301614906565b60808201526149c060a08301614922565b60a08201526149d160c083016148ed565b60c08201526149e260e083016148ed565b60e08201526101006149f581840161483d565b90820152610120614a0783820161493d565b90820152610140614a1983820161483d565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614a5a57600080fd5b614a668582860161484d565b8284015250506101e0614a7a81840161483d565b9082015292915050565b803567ffffffffffffffff8116811461484857600080fd5b600082601f830112614aad57600080fd5b813567ffffffffffffffff811115614ac757614ac761472c565b614af860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016147a8565b818152846020838601011115614b0d57600080fd5b816020850160208301376000918101602001919091529392505050565b6bffffffffffffffffffffffff811681146113e157600080fd5b600082601f830112614b5557600080fd5b81356020614b6561486e836147f7565b82815260c09283028501820192828201919087851115614b8457600080fd5b8387015b85811015614c165781818a031215614ba05760008081fd5b614ba8614785565b8135614bb3816148db565b815281860135614bc281614911565b81870152604082810135614bd58161481b565b90820152606082810135614be8816148c1565b908201526080828101359082015260a080830135614c0581614b2a565b908201528452928401928101614b88565b5090979650505050505050565b600080600080600080600080610100898b031215614c4057600080fd5b883567ffffffffffffffff80821115614c5857600080fd5b614c648c838d0161484d565b995060208b0135915080821115614c7a57600080fd5b614c868c838d0161484d565b9850614c9460408c016148d0565b975060608b0135915080821115614caa57600080fd5b614cb68c838d01614948565b9650614cc460808c01614a84565b955060a08b0135915080821115614cda57600080fd5b614ce68c838d01614a9c565b945060c08b0135915080821115614cfc57600080fd5b614d088c838d0161484d565b935060e08b0135915080821115614d1e57600080fd5b50614d2b8b828c01614b44565b9150509295985092959890939650565b6000815180845260005b81811015614d6157602081850181015186830182015201614d45565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061222c6020830184614d3b565b60008083601f840112614dc457600080fd5b50813567ffffffffffffffff811115614ddc57600080fd5b602083019150836020828501011115614df457600080fd5b9250929050565b60008060008060608587031215614e1157600080fd5b8435614e1c8161481b565b935060208501359250604085013567ffffffffffffffff811115614e3f57600080fd5b614e4b87828801614db2565b95989497509550505050565b60008083601f840112614e6957600080fd5b50813567ffffffffffffffff811115614e8157600080fd5b6020830191508360208260051b8501011115614df457600080fd5b60008060008060008060008060e0898b031215614eb857600080fd5b606089018a811115614ec957600080fd5b8998503567ffffffffffffffff80821115614ee357600080fd5b614eef8c838d01614db2565b909950975060808b0135915080821115614f0857600080fd5b614f148c838d01614e57565b909750955060a08b0135915080821115614f2d57600080fd5b50614f3a8b828c01614e57565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614f6c57600080fd5b863567ffffffffffffffff80821115614f8457600080fd5b614f908a838b0161484d565b97506020890135915080821115614fa657600080fd5b614fb28a838b0161484d565b9650614fc060408a016148d0565b95506060890135915080821115614fd657600080fd5b614fe28a838b01614a9c565b9450614ff060808a01614a84565b935060a089013591508082111561500657600080fd5b5061501389828a01614a9c565b9150509295509295509295565b60006020828403121561503257600080fd5b813561503d8161481b565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160290811690818114613a8657613a86615044565b6000602082840312156150a157600080fd5b5051919050565b63ffffffff818116838216019080821115613a8657613a86615044565b600081518084526020808501945080840160005b8381101561510b57815173ffffffffffffffffffffffffffffffffffffffff16875295820195908201906001016150d9565b509495945050505050565b6020815261512d60208201835163ffffffff169052565b60006020830151615146604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e08301516101006151c58185018363ffffffff169052565b84015190506101206151ee8482018373ffffffffffffffffffffffffffffffffffffffff169052565b84015190506101406152058482018361ffff169052565b840151905061016061522e8482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906152766102208601846150c5565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036152fc576152fc615044565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153338184018a6150c5565b9050828103608084015261534781896150c5565b905060ff871660a084015282810360c08401526153648187614d3b565b905067ffffffffffffffff851660e08401528281036101008401526153898185614d3b565b9c9b505050505050505050505050565b6000602082840312156153ab57600080fd5b5035919050565b6bffffffffffffffffffffffff818116838216019080821115613a8657613a86615044565b8082018082111561222f5761222f615044565b60ff818116838216019081111561222f5761222f615044565b8051614848816148db565b80516148488161481b565b8051614848816148f8565b805161484881614911565b80516148488161492d565b600082601f83011261544b57600080fd5b8151602061545b61486e836147f7565b82815260059290921b8401810191818101908684111561547a57600080fd5b8286015b848110156148b65780516154918161481b565b835291830191830161547e565b600082601f8301126154af57600080fd5b815160206154bf61486e836147f7565b82815260059290921b840181019181810190868411156154de57600080fd5b8286015b848110156148b65780516154f58161481b565b83529183019183016154e2565b600082601f83011261551357600080fd5b8151602061552361486e836147f7565b82815260c0928302850182019282820191908785111561554257600080fd5b8387015b85811015614c165781818a03121561555e5760008081fd5b615566614785565b8151615571816148db565b81528186015161558081614911565b818701526040828101516155938161481b565b908201526060828101516155a6816148c1565b908201526080828101519082015260a0808301516155c381614b2a565b908201528452928401928101615546565b6000806000606084860312156155e957600080fd5b835167ffffffffffffffff8082111561560157600080fd5b90850190610200828803121561561657600080fd5b61561e61475b565b61562783615403565b815261563560208401615403565b602082015261564660408401615403565b60408201526156576060840161540e565b606082015261566860808401615419565b608082015261567960a08401615424565b60a082015261568a60c08401615403565b60c082015261569b60e08401615403565b60e08201526101006156ae81850161540e565b908201526101206156c084820161542f565b908201526101406156d284820161540e565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561570b57600080fd5b6157178a82870161543a565b8284015250506101e061572b81850161540e565b90820152602087015190955091508082111561574657600080fd5b6157528783880161549e565b9350604086015191508082111561576857600080fd5b5061577586828701615502565b9150509250925092565b60006020828403121561579157600080fd5b815161503d816148c1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158128285018b6150c5565b91508382036080850152615826828a6150c5565b915060ff881660a085015283820360c08501526158438288614d3b565b90861660e085015283810361010085015290506153898185614d3b565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261589757600080fd5b813560206158a761486e836147f7565b82815260059290921b840181019181810190868411156158c657600080fd5b8286015b848110156148b657803583529183019183016158ca565b600082601f8301126158f257600080fd5b8135602061590261486e836147f7565b82815260059290921b8401810191818101908684111561592157600080fd5b8286015b848110156148b657803567ffffffffffffffff8111156159455760008081fd5b6159538986838b0101614a9c565b845250918301918301615925565b60006020828403121561597357600080fd5b813567ffffffffffffffff8082111561598b57600080fd5b9083019060c0828603121561599f57600080fd5b6159a7614785565b82358152602083013560208201526040830135828111156159c757600080fd5b6159d387828601615886565b6040830152506060830135828111156159eb57600080fd5b6159f787828601615886565b606083015250608083013582811115615a0f57600080fd5b615a1b878286016158e1565b60808301525060a083013582811115615a3357600080fd5b615a3f878286016158e1565b60a08301525095945050505050565b61ffff818116838216019080821115613a8657613a86615044565b808202811582820484141761222f5761222f615044565b8181038181111561222f5761222f615044565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615ad157615ad1615a93565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615b096080830184614d3b565b9695505050505050565b6bffffffffffffffffffffffff828116828216039080821115613a8657613a86615044565b60006bffffffffffffffffffffffff80841680615b5757615b57615a93565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615b8b57615b8b615044565b505092915050565b8281526040602082015260006135556040830184614d3b565b60008060408385031215615bbf57600080fd5b8251615bca816148f8565b6020939093015192949293505050565b805169ffffffffffffffffffff8116811461484857600080fd5b600080600080600060a08688031215615c0c57600080fd5b615c1586615bda565b9450602086015193506040860151925060608601519150615c3860808701615bda565b90509295509295909350565b6fffffffffffffffffffffffffffffffff818116838216019080821115613a8657613a86615044565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215615cae57600080fd5b6040516040810181811067ffffffffffffffff82111715615cd157615cd161472c565b6040528251615cdf816148db565b81526020928301519281019290925250919050565b600060a08284031215615d0657600080fd5b60405160a0810181811067ffffffffffffffff82111715615d2957615d2961472c565b806040525082518152602083015160208201526040830151615d4a816148db565b60408201526060830151615d5d816148db565b60608201526080928301519281019290925250919050565b600181815b80851115615dce57817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615db457615db4615044565b80851615615dc157918102915b93841c9390800290615d7a565b509250929050565b600082615de55750600161222f565b81615df25750600061222f565b8160018114615e085760028114615e1257615e2e565b600191505061222f565b60ff841115615e2357615e23615044565b50506001821b61222f565b5060208310610133831016604e8410600b8410161715615e51575081810a61222f565b615e5b8383615d75565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04821115615e8d57615e8d615044565b029392505050565b600061222c8383615dd656fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI @@ -5461,7 +5462,7 @@ func (AutomationRegistryBillingConfigOverrideRemoved) Topic() common.Hash { } func (AutomationRegistryBillingConfigSet) Topic() common.Hash { - return common.HexToHash("0x720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c") + return common.HexToHash("0xca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba3") } func (AutomationRegistryCancelledUpkeepReport) Topic() common.Hash { diff --git a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go index 7ff232e0239..a72ff506c90 100644 --- a/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go +++ b/core/gethwrappers/generated/i_automation_registry_master_wrapper_2_3/i_automation_registry_master_wrapper_2_3.go @@ -34,6 +34,7 @@ type AutomationRegistryBase23BillingConfig struct { GasFeePPB uint32 FlatFeeMilliCents *big.Int PriceFeed common.Address + Decimals uint8 FallbackPrice *big.Int MinSpend *big.Int } @@ -133,7 +134,7 @@ type IAutomationV21PlusCommonUpkeepInfoLegacy struct { } var IAutomationRegistryMaster23MetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + ABI: "[{\"inputs\":[],\"name\":\"ArrayHasNoEntries\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotCancel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CheckDataExceedsLimit\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ConfigDigestMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateEntry\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"DuplicateSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitCanOnlyIncrease\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"GasLimitOutsideRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfFaultyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSignatures\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectNumberOfSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"available\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientLinkLiquidity\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidDataLength\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFeed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidRecipient\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidReport\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTransmitter\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTrigger\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidTriggerType\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MigrationNotPermitted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOffchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MustSettleOnchain\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAContract\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveSigners\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyActiveTransmitters\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByLINKToken\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByOwnerOrRegistrar\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByProposedPayee\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableByUpkeepPrivilegeManager\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyFinanceAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyPausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlySimulatedBackend\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyUnpausedUpkeep\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ParameterLengthError\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrantCall\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RegistryPaused\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedSigner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RepeatedTransmitter\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"reason\",\"type\":\"bytes\"}],\"name\":\"TargetCheckReverted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyOracles\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TranscoderNotSet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TransferFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepCancelled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotCanceled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"UpkeepNotNeeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ValueNotChanged\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddressNotAllowed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"AdminPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"overrides\",\"type\":\"tuple\"}],\"name\":\"BillingConfigOverridden\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"BillingConfigOverrideRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"indexed\":false,\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"BillingConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"CancelledUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newModule\",\"type\":\"address\"}],\"name\":\"ChainSpecificModuleUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"previousConfigBlockNumber\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"configCount\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"onchainConfig\",\"type\":\"bytes\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"DedupKeyAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FeesWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"FundsAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"FundsWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"InsufficientFundsUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"payments\",\"type\":\"uint256[]\"}],\"name\":\"NOPsSettledOffchain\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Paused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"PayeesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"PayeeshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"name\":\"PaymentWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"ReorgedUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"StaleUpkeepReport\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"name\":\"Transmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"Unpaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"UpkeepAdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint64\",\"name\":\"atBlockHeight\",\"type\":\"uint64\"}],\"name\":\"UpkeepCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"UpkeepCheckDataSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"gasLimit\",\"type\":\"uint96\"}],\"name\":\"UpkeepGasLimitSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"UpkeepMigrated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepOffchainConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"totalPayment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gasOverhead\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"trigger\",\"type\":\"bytes\"}],\"name\":\"UpkeepPerformed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"privilegeConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepPrivilegeConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startingBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"importedFrom\",\"type\":\"address\"}],\"name\":\"UpkeepReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"UpkeepRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"UpkeepTriggerConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"UpkeepUnpaused\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"}],\"name\":\"acceptPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"acceptUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"amount\",\"type\":\"uint96\"}],\"name\":\"addFunds\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"cancelUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerData\",\"type\":\"bytes\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"checkUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fastGasWei\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"linkUSD\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disableOffchainPayments\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"payload\",\"type\":\"bytes\"}],\"name\":\"executeCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"},{\"internalType\":\"uint8\",\"name\":\"upkeepFailureReason\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fallbackTo\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveUpkeepIDs\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"}],\"name\":\"getAdminPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllowedReadOnlyAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAutomationForwarderLogic\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getBillingToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"getBillingTokenConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBillingTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCancellationDelay\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChainModule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConditionalGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFallbackNativePrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getFastGasFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepID\",\"type\":\"uint256\"}],\"name\":\"getForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getHotVars\",\"outputs\":[{\"components\":[{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reentrancyGuard\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.HotVars\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLinkUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getLogGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getMaxPaymentForGas\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"maxPayment\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getMinBalanceForUpkeep\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"minBalance\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNativeUSDFeedAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumUpkeeps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPayoutMode\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"}],\"name\":\"getPeerRegistryMigrationPermission\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerPerformByteGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getPerSignerGasOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getReorgProtectionEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"}],\"name\":\"getReserveAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getSignerInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getState\",\"outputs\":[{\"components\":[{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"ownerLinkBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"expectedLinkBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"totalPremium\",\"type\":\"uint96\"},{\"internalType\":\"uint256\",\"name\":\"numUpkeeps\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"latestConfigDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"latestEpoch\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"internalType\":\"structIAutomationV21PlusCommon.StateLegacy\",\"name\":\"state\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"paymentPremiumPPB\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeMicroLink\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"uint96\",\"name\":\"minUpkeepSpend\",\"type\":\"uint96\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"}],\"internalType\":\"structIAutomationV21PlusCommon.OnchainConfigLegacy\",\"name\":\"config\",\"type\":\"tuple\"},{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getStorage\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"nonce\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"latestConfigBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"}],\"internalType\":\"structAutomationRegistryBase2_3.Storage\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataFixedBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTransmitCalldataPerSignerBytesOverhead\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"query\",\"type\":\"address\"}],\"name\":\"getTransmitterInfo\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"},{\"internalType\":\"uint8\",\"name\":\"index\",\"type\":\"uint8\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"lastCollected\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"payee\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getTriggerType\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"getUpkeep\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"performGas\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint64\",\"name\":\"maxValidBlocknumber\",\"type\":\"uint64\"},{\"internalType\":\"uint32\",\"name\":\"lastPerformedBlockNumber\",\"type\":\"uint32\"},{\"internalType\":\"uint96\",\"name\":\"amountSpent\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"internalType\":\"structIAutomationV21PlusCommon.UpkeepInfoLegacy\",\"name\":\"upkeepInfo\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepPrivilegeConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"}],\"name\":\"getUpkeepTriggerConfig\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getWrappedNativeTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"dedupKey\",\"type\":\"bytes32\"}],\"name\":\"hasDedupKey\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDetails\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"configCount\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"blockNumber\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"latestConfigDigestAndEpoch\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"scanLogs\",\"type\":\"bool\"},{\"internalType\":\"bytes32\",\"name\":\"configDigest\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"epoch\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"},{\"internalType\":\"address\",\"name\":\"destination\",\"type\":\"address\"}],\"name\":\"migrateUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"pauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedUpkeeps\",\"type\":\"bytes\"}],\"name\":\"receiveUpkeeps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"triggerType\",\"type\":\"uint8\"},{\"internalType\":\"address\",\"name\":\"billingToken\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"registerUpkeep\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"removeBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setAdminPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingOverrides\",\"name\":\"billingOverrides\",\"type\":\"tuple\"}],\"name\":\"setBillingOverrides\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"onchainConfigBytes\",\"type\":\"bytes\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"signers\",\"type\":\"address[]\"},{\"internalType\":\"address[]\",\"name\":\"transmitters\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"f\",\"type\":\"uint8\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"checkGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformGas\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxCheckDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"transcoder\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"reorgProtectionEnabled\",\"type\":\"bool\"},{\"internalType\":\"uint24\",\"name\":\"stalenessSeconds\",\"type\":\"uint24\"},{\"internalType\":\"uint32\",\"name\":\"maxPerformDataSize\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"maxRevertDataSize\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"upkeepPrivilegeManager\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"gasCeilingMultiplier\",\"type\":\"uint16\"},{\"internalType\":\"address\",\"name\":\"financeAdmin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"fallbackGasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackLinkPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"fallbackNativePrice\",\"type\":\"uint256\"},{\"internalType\":\"address[]\",\"name\":\"registrars\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"chainModule\",\"type\":\"address\"}],\"internalType\":\"structAutomationRegistryBase2_3.OnchainConfig\",\"name\":\"onchainConfig\",\"type\":\"tuple\"},{\"internalType\":\"uint64\",\"name\":\"offchainConfigVersion\",\"type\":\"uint64\"},{\"internalType\":\"bytes\",\"name\":\"offchainConfig\",\"type\":\"bytes\"},{\"internalType\":\"address[]\",\"name\":\"billingTokens\",\"type\":\"address[]\"},{\"components\":[{\"internalType\":\"uint32\",\"name\":\"gasFeePPB\",\"type\":\"uint32\"},{\"internalType\":\"uint24\",\"name\":\"flatFeeMilliCents\",\"type\":\"uint24\"},{\"internalType\":\"address\",\"name\":\"priceFeed\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"decimals\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"fallbackPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"minSpend\",\"type\":\"uint96\"}],\"internalType\":\"structAutomationRegistryBase2_3.BillingConfig[]\",\"name\":\"billingConfigs\",\"type\":\"tuple[]\"}],\"name\":\"setConfigTypeSafe\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"payees\",\"type\":\"address[]\"}],\"name\":\"setPayees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"peer\",\"type\":\"address\"},{\"internalType\":\"uint8\",\"name\":\"permission\",\"type\":\"uint8\"}],\"name\":\"setPeerRegistryMigrationPermission\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newCheckData\",\"type\":\"bytes\"}],\"name\":\"setUpkeepCheckData\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"gasLimit\",\"type\":\"uint32\"}],\"name\":\"setUpkeepGasLimit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"config\",\"type\":\"bytes\"}],\"name\":\"setUpkeepOffchainConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"upkeepId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"newPrivilegeConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepPrivilegeConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"triggerConfig\",\"type\":\"bytes\"}],\"name\":\"setUpkeepTriggerConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"settleNOPsOffchain\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"simulatePerformUpkeep\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"gasUsed\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"supportsBillingToken\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"transmitter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferPayeeship\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"proposed\",\"type\":\"address\"}],\"name\":\"transferUpkeepAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32[3]\",\"name\":\"reportContext\",\"type\":\"bytes32[3]\"},{\"internalType\":\"bytes\",\"name\":\"rawReport\",\"type\":\"bytes\"},{\"internalType\":\"bytes32[]\",\"name\":\"rs\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"ss\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32\",\"name\":\"rawVs\",\"type\":\"bytes32\"}],\"name\":\"transmit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unpause\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"}],\"name\":\"unpauseUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawERC20Fees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"id\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawLink\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"withdrawPayment\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", } var IAutomationRegistryMaster23ABI = IAutomationRegistryMaster23MetaData.ABI @@ -7070,7 +7071,7 @@ func (IAutomationRegistryMaster23BillingConfigOverrideRemoved) Topic() common.Ha } func (IAutomationRegistryMaster23BillingConfigSet) Topic() common.Hash { - return common.HexToHash("0x720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c") + return common.HexToHash("0xca93cbe727c73163ec538f71be6c0a64877d7f1f6dd35d5ca7cbaef3a3e34ba3") } func (IAutomationRegistryMaster23CancelledUpkeepReport) Topic() common.Hash { diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 4cee5f8be1c..d7a1fa84424 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -8,13 +8,13 @@ automation_compatible_utils: ../../contracts/solc/v0.8.19/AutomationCompatibleUt automation_consumer_benchmark: ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.abi ../../contracts/solc/v0.8.16/AutomationConsumerBenchmark/AutomationConsumerBenchmark.bin f52c76f1aaed4be541d82d97189d70f5aa027fc9838037dd7a7d21910c8c488e automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.abi ../../contracts/solc/v0.8.16/AutomationForwarderLogic/AutomationForwarderLogic.bin 15ae0c367297955fdab4b552dbb10e1f2be80a8fde0efec4a4d398693e9d72b5 automation_registrar_wrapper2_1: ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.abi ../../contracts/solc/v0.8.16/AutomationRegistrar2_1/AutomationRegistrar2_1.bin eb06d853aab39d3196c593b03e555851cbe8386e0fe54a74c2479f62d14b3c42 -automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin f07ffea17d8d7c2bd5ea91c25a32e2fa64aa6bffbd81a3281ebdb9b542535202 +automation_registrar_wrapper2_3: ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistrar2_3/AutomationRegistrar2_3.bin b42de91c15c7453d8262124e20594819d64a3f23bef8e6db66fa5180d18a8454 automation_registry_logic_a_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_2/AutomationRegistryLogicA2_2.bin 2f267fb8467a15c587ce4586ac56069f7229344ad3936430d7c7624c0528a171 -automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 918082df412d3138c727871545fbcff7d9c9724e56990f8e5e0ab93809f83364 +automation_registry_logic_a_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicA2_3/AutomationRegistryLogicA2_3.bin 1163ecd34c575cb17ffbc2f88fa175816f36982e91992d940ed435d306b3418c automation_registry_logic_b_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_2/AutomationRegistryLogicB2_2.bin a6d33dfbbfb0ff253eb59a51f4f6d6d4c22ea5ec95aae52d25d49a312b37a22f -automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin b811c11616795e82e416cb8deff85b4d90b9c15f0aea23a5ea35a0d61c37dffc +automation_registry_logic_b_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistryLogicB2_3/AutomationRegistryLogicB2_3.bin 2d0f45d2087f6f3c8bfa0a16b26a1c8c1d5c64b89859478c609201535c96eeed automation_registry_wrapper_2_2: ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_2/AutomationRegistry2_2.bin de60f69878e9b32a291a001c91fc8636544c2cfbd9b507c8c1a4873b602bfb62 -automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin 9aaed50d72437f3882b64f69018606d97f13f9b7c4e4b82ad0da66f2694be433 +automation_registry_wrapper_2_3: ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.abi ../../contracts/solc/v0.8.19/AutomationRegistry2_3/AutomationRegistry2_3.bin 2f9db5da86183eaf4f78f726458e5a928d37f7c90c4024923847b25186b644c5 automation_utils_2_1: ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.abi ../../contracts/solc/v0.8.16/AutomationUtils2_1/AutomationUtils2_1.bin 815b17b63f15d26a0274b962eefad98cdee4ec897ead58688bbb8e2470e585f5 automation_utils_2_2: ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.abi ../../contracts/solc/v0.8.19/AutomationUtils2_2/AutomationUtils2_2.bin 8743f6231aaefa3f2a0b2d484258070d506e2d0860690e66890dccc3949edb2e automation_utils_2_3: ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.abi ../../contracts/solc/v0.8.19/AutomationUtils2_3/AutomationUtils2_3.bin 11e2b481dc9a4d936e3443345d45d2cc571164459d214917b42a8054b295393b @@ -31,7 +31,7 @@ dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol gas_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2/KeeperRegistryCheckUpkeepGasUsageWrapper1_2.bin 4a5dcdac486d18fcd58e3488c15c1710ae76b977556a3f3191bd269a4bc75723 gas_wrapper_mock: ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.abi ../../contracts/solc/v0.8.6/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock/KeeperRegistryCheckUpkeepGasUsageWrapper1_2Mock.bin a9b08f18da59125c6fc305855710241f3d35161b8b9f3e3f635a7b1d5c6da9c8 i_automation_registry_master_wrapper_2_2: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster/IAutomationRegistryMaster.bin 9ff7087179f89f9b05964ebc3e71332fce11f1b8e85058f7b16b3bc0dd6fb96b -i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin 16b346a64126554bad0929f49ce020d886cc7203d03ca52c4537daf273b4c369 +i_automation_registry_master_wrapper_2_3: ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.abi ../../contracts/solc/v0.8.19/IAutomationRegistryMaster2_3/IAutomationRegistryMaster2_3.bin fbfa3f5d78a357ecb7a1bc597c629ff30d42fedc48ba7f57e1622a6302d36523 i_automation_v21_plus_common: ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.abi ../../contracts/solc/v0.8.19/IAutomationV21PlusCommon/IAutomationV21PlusCommon.bin e8a601ec382c0a2e83c49759de13b0622b5e04e6b95901e96a1e9504329e594c i_chain_module: ../../contracts/solc/v0.8.19/IChainModule/IChainModule.abi ../../contracts/solc/v0.8.19/IChainModule/IChainModule.bin 383611981c86c70522f41b8750719faacc7d7933a22849d5004799ebef3371fa i_keeper_registry_master_wrapper_2_1: ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.abi ../../contracts/solc/v0.8.16/IKeeperRegistryMaster/IKeeperRegistryMaster.bin ee0f150b3afbab2df3d24ff3f4c87851efa635da30db04cd1f70cb4e185a1781 From 2b38bd8738b4edf16e9913c90720820bc2b8dbd1 Mon Sep 17 00:00:00 2001 From: Erik Burton Date: Thu, 18 Apr 2024 13:35:51 -0700 Subject: [PATCH 11/26] RE-2169: chore: bump postgres client from 15 to 16 (#11936) * chore: bump postgres client from 15 to 16 * chore: bump postgres client from 15 to 16 (plugins) * fix: add changeset for postgres-client version bump --- .changeset/lucky-windows-taste.md | 5 +++++ README.md | 2 +- core/chainlink.Dockerfile | 2 +- core/chainlink.goreleaser.Dockerfile | 2 +- plugins/chainlink.Dockerfile | 2 +- 5 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 .changeset/lucky-windows-taste.md diff --git a/.changeset/lucky-windows-taste.md b/.changeset/lucky-windows-taste.md new file mode 100644 index 00000000000..bfcf559adb5 --- /dev/null +++ b/.changeset/lucky-windows-taste.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Validate support for postgresql-client 16, and update docker image's bundled postgresql-client from 15 to 16. #nops #updated diff --git a/README.md b/README.md index 0d336dd22b3..167fae4adee 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ regarding Chainlink social accounts, news, and networking. 2. Install [NodeJS v16](https://nodejs.org/en/download/package-manager/) & [pnpm via npm](https://pnpm.io/installation#using-npm). - It might be easier long term to use [nvm](https://nodejs.org/en/download/package-manager/#nvm) to switch between node versions for different projects. For example, assuming $NODE_VERSION was set to a valid version of NodeJS, you could run: `nvm install $NODE_VERSION && nvm use $NODE_VERSION` 3. Install [Postgres (>= 12.x)](https://wiki.postgresql.org/wiki/Detailed_installation_guides). It is recommended to run the latest major version of postgres. - - Note if you are running the official Chainlink docker image, the highest supported Postgres version is 15.x due to the bundled client. + - Note if you are running the official Chainlink docker image, the highest supported Postgres version is 16.x due to the bundled client. - You should [configure Postgres](https://www.postgresql.org/docs/current/ssl-tcp.html) to use SSL connection (or for testing you can set `?sslmode=disable` in your Postgres query string). 4. Ensure you have Python 3 installed (this is required by [solc-select](https://github.com/crytic/solc-select) which is needed to compile solidity contracts) 5. Download Chainlink: `git clone https://github.com/smartcontractkit/chainlink && cd chainlink` diff --git a/core/chainlink.Dockerfile b/core/chainlink.Dockerfile index e82a4cd662c..4aa447b5ddd 100644 --- a/core/chainlink.Dockerfile +++ b/core/chainlink.Dockerfile @@ -45,7 +45,7 @@ RUN apt-get update && apt-get install -y ca-certificates gnupg lsb-release curl # Install Postgres for CLI tools, needed specifically for DB backups RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |tee /etc/apt/sources.list.d/pgdg.list \ - && apt-get update && apt-get install -y postgresql-client-15 \ + && apt-get update && apt-get install -y postgresql-client-16 \ && apt-get clean all \ && rm -rf /var/lib/apt/lists/* diff --git a/core/chainlink.goreleaser.Dockerfile b/core/chainlink.goreleaser.Dockerfile index 7dab088116e..5d172fd77e5 100644 --- a/core/chainlink.goreleaser.Dockerfile +++ b/core/chainlink.goreleaser.Dockerfile @@ -11,7 +11,7 @@ RUN apt-get update && apt-get install -y ca-certificates gnupg lsb-release curl # Install Postgres for CLI tools, needed specifically for DB backups RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |tee /etc/apt/sources.list.d/pgdg.list \ - && apt-get update && apt-get install -y postgresql-client-15 \ + && apt-get update && apt-get install -y postgresql-client-16 \ && apt-get clean all \ && rm -rf /var/lib/apt/lists/* diff --git a/plugins/chainlink.Dockerfile b/plugins/chainlink.Dockerfile index 9c7f71183f0..50986396296 100644 --- a/plugins/chainlink.Dockerfile +++ b/plugins/chainlink.Dockerfile @@ -62,7 +62,7 @@ RUN apt-get update && apt-get install -y ca-certificates gnupg lsb-release curl # Install Postgres for CLI tools, needed specifically for DB backups RUN curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - \ && echo "deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main" |tee /etc/apt/sources.list.d/pgdg.list \ - && apt-get update && apt-get install -y postgresql-client-14 \ + && apt-get update && apt-get install -y postgresql-client-16 \ && apt-get clean all COPY --from=buildgo /go/bin/chainlink /usr/local/bin/ From 2a0c7b80e98d96af2d0359da84edd01638eee1d2 Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Thu, 18 Apr 2024 23:53:42 +0300 Subject: [PATCH 12/26] VRF-1025: adjust BHS load test to be used as a smoke test (#12884) * VRF-1025: adjust BHS load test to be used as a smoke test * VRF-1025: fix lint * VRF-1025: reverting change of log level; fixing lint --- .../on-demand-vrfv2-performance-test.yml | 6 +- .../on-demand-vrfv2plus-performance-test.yml | 9 +- .../actions/vrf/vrfv2plus/contract_steps.go | 5 +- integration-tests/load/vrfv2/vrfv2_test.go | 112 ++++++++++-------- .../load/vrfv2plus/vrfv2plus_test.go | 106 ++++++++++------- integration-tests/smoke/vrfv2_test.go | 8 +- integration-tests/smoke/vrfv2plus_test.go | 17 +-- 7 files changed, 150 insertions(+), 113 deletions(-) diff --git a/.github/workflows/on-demand-vrfv2-performance-test.yml b/.github/workflows/on-demand-vrfv2-performance-test.yml index 860120972d5..f520e2307d9 100644 --- a/.github/workflows/on-demand-vrfv2-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2-performance-test.yml @@ -15,6 +15,10 @@ on: - "Load" - "Stress" - "Spike" + test_list_regex: + description: "Regex for tests to run" + required: false + default: "(TestVRFV2Performance)" jobs: vrfv2_performance_test: name: VRFV2 Performance Test @@ -71,7 +75,7 @@ jobs: - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 with: - test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run TestVRFV2Performance ./vrfv2 + test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2 test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ env.CHAINLINK_VERSION }} diff --git a/.github/workflows/on-demand-vrfv2plus-performance-test.yml b/.github/workflows/on-demand-vrfv2plus-performance-test.yml index 463a7512b0c..16d37617a68 100644 --- a/.github/workflows/on-demand-vrfv2plus-performance-test.yml +++ b/.github/workflows/on-demand-vrfv2plus-performance-test.yml @@ -14,8 +14,11 @@ on: - "Soak" - "Load" - "Stress" - - "Spike" - + - "Spike" + test_list_regex: + description: "Regex for tests to run" + required: false + default: "(TestVRFV2PlusPerformance)" jobs: vrfv2plus_performance_test: name: VRFV2 Plus Performance Test @@ -72,7 +75,7 @@ jobs: - name: Run Tests uses: smartcontractkit/chainlink-github-actions/chainlink-testing-framework/run-tests@5dd916d08c03cb5f9a97304f4f174820421bb946 # v2.3.11 with: - test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run TestVRFV2PlusPerformance ./vrfv2plus + test_command_to_run: cd ./integration-tests/load && go test -v -count=1 -timeout 24h -run "${{ inputs.test_list_regex }}" ./vrfv2plus test_download_vendor_packages_command: cd ./integration-tests && go mod download cl_repo: ${{ env.CHAINLINK_IMAGE }} cl_image_tag: ${{ env.CHAINLINK_VERSION }} diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 5df33a6d997..acc509fb58b 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -762,15 +762,12 @@ func SetupNewConsumersAndSubs( ) ([]contracts.VRFv2PlusLoadTestConsumer, []*big.Int, error) { consumers, err := DeployVRFV2PlusConsumers(env.ContractDeployer, coordinator, consumerContractsAmount) if err != nil { - if err != nil { - return nil, nil, fmt.Errorf("err: %w", err) - } + return nil, nil, fmt.Errorf("err: %w", err) } evmClient, err := env.GetEVMClient(chainID) if err != nil { return nil, nil, err } - err = evmClient.WaitForEvents() if err != nil { return nil, nil, fmt.Errorf("%s, err: %w", vrfcommon.ErrWaitTXsComplete, err) diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index 0edf35df8fa..b27395769db 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -26,12 +26,6 @@ import ( ) var ( - testEnv *test_env.CLClusterTestEnv - vrfContracts *vrfcommon.VRFContracts - vrfKey *vrfcommon.VRFKeyData - subIDs []uint64 - eoaWalletAddress string - labels = map[string]string{ "branch": "vrfv2_healthcheck", "commit": "vrfv2_healthcheck", @@ -39,24 +33,30 @@ var ( ) func TestVRFV2Performance(t *testing.T) { + var ( + testEnv *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []uint64 + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) l := logging.GetTestLogger(t) - testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) testConfig, err := tc.GetConfig(testType, tc.VRFv2) require.NoError(t, err) + cfgl := testConfig.Logging.Loki - testReporter := &testreporters.VRFV2TestReporter{} vrfv2Config := testConfig.VRFv2 + testReporter := &testreporters.VRFV2TestReporter{} - cfgl := testConfig.Logging.Loki lokiConfig := wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken) lc, err := wasp.NewLokiClient(lokiConfig) if err != nil { l.Error().Err(err).Msg(ErrLokiClient) return } - + chainID := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0].ChainID updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -68,9 +68,6 @@ func TestVRFV2Performance(t *testing.T) { Uint16("RandomnessRequestCountPerRequestDeviation", *vrfv2Config.General.RandomnessRequestCountPerRequestDeviation). Bool("UseExistingEnv", *vrfv2Config.General.UseExistingEnv). Msg("Performance Test Configuration") - - chainID := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0].ChainID - cleanupFn := func() { teardown(t, vrfContracts.VRFV2Consumers[0], lc, updatedLabels, testReporter, testType, &testConfig) @@ -84,7 +81,7 @@ func TestVRFV2Performance(t *testing.T) { } else { if *vrfv2Config.General.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, eoaWalletAddress, subIDs, l) + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) } } if !*vrfv2Config.General.UseExistingEnv { @@ -108,7 +105,7 @@ func TestVRFV2Performance(t *testing.T) { require.NoError(t, err, "error getting EVM client") var consumers []contracts.VRFv2LoadTestConsumer - subIDs, consumers, err = vrfv2.SetupSubsAndConsumersForExistingEnv( + subIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( testEnv, chainID, vrfContracts.CoordinatorV2, @@ -118,16 +115,17 @@ func TestVRFV2Performance(t *testing.T) { testConfig, l, ) - vrfContracts.VRFV2Consumers = consumers - - eoaWalletAddress = evmClient.GetDefaultWallet().Address() - - l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") + require.NoError(t, err, "error setting up new consumers and subs") for _, subID := range subIDs { subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %d", subID) vrfv2.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2) } + subIDsForCancellingAfterTest = subIDs + l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") + + vrfContracts.VRFV2Consumers = consumers + defaultWalletAddress = evmClient.GetDefaultWallet().Address() // is our "job" stable at all, no memory leaks, no flaking performance under some RPS? t.Run("vrfv2 performance test", func(t *testing.T) { @@ -177,16 +175,21 @@ func TestVRFV2Performance(t *testing.T) { } func TestVRFV2BHSPerformance(t *testing.T) { + var ( + testEnv *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []uint64 + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) testConfig, err := tc.GetConfig(testType, tc.VRFv2) require.NoError(t, err) - - testReporter := &testreporters.VRFV2TestReporter{} vrfv2Config := testConfig.VRFv2 - + testReporter := &testreporters.VRFV2TestReporter{} cfgl := testConfig.Logging.Loki lokiConfig := wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken) lc, err := wasp.NewLokiClient(lokiConfig) @@ -222,7 +225,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { } else { if *vrfv2Config.General.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner - vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, eoaWalletAddress, subIDs, l) + vrfv2.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) } } if !*vrfv2Config.General.UseExistingEnv { @@ -245,43 +248,29 @@ func TestVRFV2BHSPerformance(t *testing.T) { evmClient, err := testEnv.GetEVMClient(chainID) require.NoError(t, err, "error getting EVM client") - var consumers []contracts.VRFv2LoadTestConsumer - subIDs, consumers, err = vrfv2.SetupSubsAndConsumersForExistingEnv( - testEnv, - chainID, - vrfContracts.CoordinatorV2, - vrfContracts.LinkToken, - 1, - *vrfv2Config.General.NumberOfSubToCreate, - testConfig, - l, - ) - vrfContracts.VRFV2Consumers = consumers - - eoaWalletAddress = evmClient.GetDefaultWallet().Address() - - l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") - for _, subID := range subIDs { - subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) - require.NoError(t, err, "error getting subscription information for subscription %d", subID) - vrfv2.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2) - } - + defaultWalletAddress = evmClient.GetDefaultWallet().Address() t.Run("vrfv2 and bhs performance test", func(t *testing.T) { configCopy := testConfig.MustCopy().(tc.TestConfig) //Underfund Subscription configCopy.VRFv2.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) - consumers, subIDs, err = vrfv2.SetupNewConsumersAndSubs( + underfundedSubIDs, consumers, err := vrfv2.SetupSubsAndConsumersForExistingEnv( testEnv, chainID, vrfContracts.CoordinatorV2, - configCopy, vrfContracts.LinkToken, 1, - *configCopy.VRFv2.General.NumberOfSubToCreate, + *vrfv2Config.General.NumberOfSubToCreate, + configCopy, l, ) - require.NoError(t, err, "error setting up new consumers and subscriptions") + require.NoError(t, err, "error setting up new consumers and subs") + for _, subID := range underfundedSubIDs { + subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information for subscription %d", subID) + vrfv2.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2) + } + subIDsForCancellingAfterTest = underfundedSubIDs + l.Debug().Int("Number of Subs", len(underfundedSubIDs)).Msg("Subs involved in the test") vrfContracts.VRFV2Consumers = consumers require.Len(t, vrfContracts.VRFV2Consumers, 1, "only one consumer should be created for Load Test") err = vrfContracts.VRFV2Consumers[0].ResetMetrics() @@ -296,7 +285,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { Gun: NewBHSTestGun( vrfContracts, vrfKey.KeyHash, - subIDs, + underfundedSubIDs, configCopy.VRFv2, l, ), @@ -322,8 +311,27 @@ func TestVRFV2BHSPerformance(t *testing.T) { _, err = actions.WaitForBlockNumberToBe(latestBlockNumber+uint64(256), evmClient, &wgBlockNumberTobe, configCopy.VRFv2.General.WaitFor256BlocksTimeout.Duration, t) wgBlockNumberTobe.Wait() require.NoError(t, err, "error waiting for block number to be") - err = vrfv2.FundSubscriptions(testEnv, chainID, big.NewFloat(*configCopy.VRFv2.General.SubscriptionRefundingAmountLink), vrfContracts.LinkToken, vrfContracts.CoordinatorV2, subIDs) + + metrics, err := consumers[0].GetLoadTestMetrics(testcontext.Get(t)) + require.NoError(t, err) + require.Equal(t, 0, metrics.FulfilmentCount.Cmp(big.NewInt(0)), "Fulfilment count should be 0 since sub is underfunded. Check if the sub is actually funded") + + var subIDsString []uint64 + subIDsString = append(subIDsString, underfundedSubIDs...) + l.Info(). + Float64("SubscriptionRefundingAmountLink", *configCopy.VRFv2.General.SubscriptionRefundingAmountLink). + Uints64("SubIDs", subIDsString). + Msg("Funding Subscriptions with Link and Native Tokens") + err = vrfv2.FundSubscriptions( + testEnv, + chainID, + big.NewFloat(*configCopy.VRFv2.General.SubscriptionRefundingAmountLink), + vrfContracts.LinkToken, + vrfContracts.CoordinatorV2, + underfundedSubIDs, + ) require.NoError(t, err, "error funding subscriptions") + var wgAllRequestsFulfilled sync.WaitGroup wgAllRequestsFulfilled.Add(1) requestCount, fulfilmentCount, err := vrfcommon.WaitForRequestCountEqualToFulfilmentCount(testcontext.Get(t), vrfContracts.VRFV2Consumers[0], 2*time.Minute, &wgAllRequestsFulfilled) diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index 1589123c77e..bb9c33f43a6 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -26,12 +26,6 @@ import ( ) var ( - testEnv *test_env.CLClusterTestEnv - vrfContracts *vrfcommon.VRFContracts - vrfKey *vrfcommon.VRFKeyData - subIDs []*big.Int - eoaWalletAddress string - labels = map[string]string{ "branch": "vrfv2Plus_healthcheck", "commit": "vrfv2Plus_healthcheck", @@ -39,8 +33,14 @@ var ( ) func TestVRFV2PlusPerformance(t *testing.T) { + var ( + testEnv *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) l := logging.GetTestLogger(t) - testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) testConfig, err := tc.GetConfig(testType, tc.VRFv2Plus) @@ -56,8 +56,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { l.Error().Err(err).Msg(ErrLokiClient) return } - - networkConfig := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0] + chainID := networks.MustGetSelectedNetworkConfig(testConfig.GetNetworkConfig())[0].ChainID updatedLabels := UpdateLabels(labels, t) l.Info(). @@ -73,8 +72,8 @@ func TestVRFV2PlusPerformance(t *testing.T) { cleanupFn := func() { teardown(t, vrfContracts.VRFV2PlusConsumer[0], lc, updatedLabels, testReporter, testType, &testConfig) - evmClient, err := testEnv.GetEVMClient(networkConfig.ChainID) - require.NoError(t, err, "Getting EVM client shouldn't fail") + evmClient, err := testEnv.GetEVMClient(chainID) + require.NoError(t, err, "error getting EVM client") if evmClient.NetworkSimulated() { l.Info(). @@ -83,7 +82,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { } else { if *testConfig.VRFv2Plus.General.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, eoaWalletAddress, subIDs, l) + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) } } if !*testConfig.VRFv2Plus.General.UseExistingEnv { @@ -98,16 +97,16 @@ func TestVRFV2PlusPerformance(t *testing.T) { NumberOfTxKeysToCreate: *vrfv2PlusConfig.General.NumberOfSendingKeysToCreate, } - testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, testConfig, networkConfig.ChainID, cleanupFn, newEnvConfig, l) + testEnv, vrfContracts, vrfKey, _, err = vrfv2plus.SetupVRFV2PlusUniverse(testcontext.Get(t), t, testConfig, chainID, cleanupFn, newEnvConfig, l) require.NoError(t, err, "error setting up VRFV2Plus universe") - evmClient, err := testEnv.GetEVMClient(networkConfig.ChainID) + evmClient, err := testEnv.GetEVMClient(chainID) require.NoError(t, err, "Getting EVM client shouldn't fail") var consumers []contracts.VRFv2PlusLoadTestConsumer - subIDs, consumers, err = vrfv2plus.SetupSubsAndConsumersForExistingEnv( + subIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testEnv, - networkConfig.ChainID, + chainID, vrfContracts.CoordinatorV2Plus, vrfContracts.LinkToken, 1, @@ -115,19 +114,26 @@ func TestVRFV2PlusPerformance(t *testing.T) { testConfig, l, ) - vrfContracts.VRFV2PlusConsumer = consumers - - eoaWalletAddress = evmClient.GetDefaultWallet().Address() - - l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") + require.NoError(t, err, "error setting up new consumers and subs") for _, subID := range subIDs { subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %s", subID.String()) vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) } + subIDsForCancellingAfterTest = subIDs + l.Info().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") + + vrfContracts.VRFV2PlusConsumer = consumers + defaultWalletAddress = evmClient.GetDefaultWallet().Address() // is our "job" stable at all, no memory leaks, no flaking performance under some RPS? t.Run("vrfv2plus performance test", func(t *testing.T) { + require.Len(t, vrfContracts.VRFV2PlusConsumer, 1, "only one consumer should be created for Load Test") + consumer := vrfContracts.VRFV2PlusConsumer[0] + err = consumer.ResetMetrics() + require.NoError(t, err) + MonitorLoadStats(testcontext.Get(t), lc, consumer, updatedLabels) + singleFeedConfig := &wasp.Config{ T: t, LoadType: wasp.RPS, @@ -144,11 +150,6 @@ func TestVRFV2PlusPerformance(t *testing.T) { LokiConfig: wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken), CallTimeout: 2 * time.Minute, } - require.Len(t, vrfContracts.VRFV2PlusConsumer, 1, "only one consumer should be created for Load Test") - consumer := vrfContracts.VRFV2PlusConsumer[0] - err = consumer.ResetMetrics() - require.NoError(t, err) - MonitorLoadStats(testcontext.Get(t), lc, consumer, updatedLabels) singleFeedConfig.Schedule = wasp.Plain( *vrfv2PlusConfig.Performance.RPS, @@ -174,17 +175,22 @@ func TestVRFV2PlusPerformance(t *testing.T) { } func TestVRFV2PlusBHSPerformance(t *testing.T) { + var ( + testEnv *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + ) l := logging.GetTestLogger(t) testType, err := tc.GetConfigurationNameFromEnv() require.NoError(t, err) testConfig, err := tc.GetConfig(testType, tc.VRFv2Plus) require.NoError(t, err) - cfgl := testConfig.Logging.Loki - vrfv2PlusConfig := testConfig.VRFv2Plus testReporter := &testreporters.VRFV2PlusTestReporter{} - + cfgl := testConfig.Logging.Loki lokiConfig := wasp.NewLokiConfig(cfgl.Endpoint, cfgl.TenantId, cfgl.BasicAuth, cfgl.BearerToken) lc, err := wasp.NewLokiClient(lokiConfig) if err != nil { @@ -219,7 +225,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { } else { if *testConfig.VRFv2Plus.General.CancelSubsAfterTestRun { //cancel subs and return funds to sub owner - vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, eoaWalletAddress, subIDs, l) + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) } } if !*testConfig.VRFv2Plus.General.UseExistingEnv { @@ -240,30 +246,32 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { evmClient, err := testEnv.GetEVMClient(chainID) require.NoError(t, err, "error getting EVM client") - eoaWalletAddress = evmClient.GetDefaultWallet().Address() - - l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") - for _, subID := range subIDs { - subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) - require.NoError(t, err, "error getting subscription information for subscription %s", subID.String()) - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) - } + defaultWalletAddress = evmClient.GetDefaultWallet().Address() t.Run("vrfv2plus and bhs performance test", func(t *testing.T) { configCopy := testConfig.MustCopy().(tc.TestConfig) //Underfund Subscription configCopy.VRFv2Plus.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) - consumers, underfundedSubIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + configCopy.VRFv2Plus.General.SubscriptionFundingAmountNative = ptr.Ptr(float64(0)) + + underfundedSubIDs, consumers, err := vrfv2plus.SetupSubsAndConsumersForExistingEnv( testEnv, chainID, vrfContracts.CoordinatorV2Plus, - configCopy, vrfContracts.LinkToken, 1, - *configCopy.VRFv2Plus.General.NumberOfSubToCreate, + *vrfv2PlusConfig.General.NumberOfSubToCreate, + configCopy, l, ) require.NoError(t, err, "error setting up new consumers and subs for Load Test") + for _, subID := range underfundedSubIDs { + subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) + require.NoError(t, err, "error getting subscription information for subscription %s", subID.String()) + vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + } + subIDsForCancellingAfterTest = underfundedSubIDs + l.Debug().Int("Number of Subs", len(underfundedSubIDs)).Msg("Subs involved in the test") vrfContracts.VRFV2PlusConsumer = consumers require.Len(t, vrfContracts.VRFV2PlusConsumer, 1, "only one consumer should be created for Load Test") consumer := vrfContracts.VRFV2PlusConsumer[0] @@ -306,6 +314,20 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { wgBlockNumberTobe.Wait() require.NoError(t, err, "error waiting for block number to be") + metrics, err := consumers[0].GetLoadTestMetrics(testcontext.Get(t)) + require.NoError(t, err) + require.Equal(t, 0, metrics.FulfilmentCount.Cmp(big.NewInt(0)), "Fulfilment count should be 0 since sub is underfunded. Check if the sub is actually funded") + + var subIDsString []string + for _, subID := range underfundedSubIDs { + subIDsString = append(subIDsString, subID.String()) + } + + l.Info(). + Float64("SubscriptionRefundingAmountNative", *configCopy.VRFv2Plus.General.SubscriptionRefundingAmountNative). + Float64("SubscriptionRefundingAmountLink", *configCopy.VRFv2Plus.General.SubscriptionRefundingAmountLink). + Strs("SubIDs", subIDsString). + Msg("Funding Subscriptions with Link and Native Tokens") err = vrfv2plus.FundSubscriptions( testEnv, chainID, @@ -313,7 +335,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { big.NewFloat(*configCopy.VRFv2Plus.General.SubscriptionRefundingAmountLink), vrfContracts.LinkToken, vrfContracts.CoordinatorV2Plus, - subIDs, + underfundedSubIDs, ) require.NoError(t, err, "error funding subscriptions") diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index 9834cd77973..a834d1be757 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -126,7 +126,7 @@ func TestVRFv2Basic(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { @@ -748,7 +748,7 @@ func TestVRFOwner(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") require.Equal(t, *configCopy.VRFv2.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { @@ -886,7 +886,7 @@ func TestVRFV2WithBHS(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") }) t.Run("BHS Job should fill in blockhashes into BHS contract for unfulfilled requests", func(t *testing.T) { @@ -949,7 +949,7 @@ func TestVRFV2WithBHS(t *testing.T) { gom.Eventually(func(g gomega.Gomega) { clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") - l.Debug().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") + l.Info().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) txHash = clNodeTxs.Data[0].Attributes.Hash }, "2m", "1s").Should(gomega.Succeed()) diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index c5a35704b1a..2f58c2d0003 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -136,7 +136,7 @@ func TestVRFv2Plus(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") require.Equal(t, *configCopy.VRFv2Plus.General.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { @@ -198,7 +198,7 @@ func TestVRFv2Plus(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") require.Equal(t, *testConfig.NumberOfWords, uint32(len(status.RandomWords))) for _, w := range status.RandomWords { @@ -939,7 +939,7 @@ func TestVRFv2PlusMigration(t *testing.T) { coordinatorAddressInConsumerAfterMigration, err := consumer.GetCoordinator(testcontext.Get(t)) require.NoError(t, err, "error getting Coordinator from Consumer contract") require.Equal(t, newCoordinator.Address(), coordinatorAddressInConsumerAfterMigration.String()) - l.Debug(). + l.Info(). Str("Consumer", consumer.Address()). Str("Coordinator", coordinatorAddressInConsumerAfterMigration.String()). Msg("Coordinator Address in Consumer After Migration") @@ -1123,7 +1123,7 @@ func TestVRFv2PlusMigration(t *testing.T) { coordinatorAddressInConsumerAfterMigration, err := wrapperContracts.VRFV2PlusWrapper.Coordinator(testcontext.Get(t)) require.NoError(t, err, "error getting Coordinator from Consumer contract- VRFV2PlusWrapper") require.Equal(t, newCoordinator.Address(), coordinatorAddressInConsumerAfterMigration.String()) - l.Debug(). + l.Info(). Str("Consumer-VRFV2PlusWrapper", wrapperContracts.VRFV2PlusWrapper.Address()). Str("Coordinator", coordinatorAddressInConsumerAfterMigration.String()). Msg("Coordinator Address in VRFV2PlusWrapper After Migration") @@ -1318,7 +1318,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") randRequestBlockHash, err := vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.NoError(t, err, "error getting blockhash for a blocknumber which was stored in BHS contract") @@ -1385,6 +1385,9 @@ func TestVRFV2PlusWithBHS(t *testing.T) { err = evmClient.WaitForEvents() require.NoError(t, err, vrfcommon.ErrWaitTXsComplete) + metrics, err := consumers[0].GetLoadTestMetrics(testcontext.Get(t)) + require.Equal(t, 0, metrics.RequestCount.Cmp(big.NewInt(1))) + require.Equal(t, 0, metrics.FulfilmentCount.Cmp(big.NewInt(0))) var clNodeTxs *client.TransactionsData var txHash string @@ -1392,7 +1395,7 @@ func TestVRFV2PlusWithBHS(t *testing.T) { gom.Eventually(func(g gomega.Gomega) { clNodeTxs, _, err = nodeTypeToNodeMap[vrfcommon.BHS].CLNode.API.ReadTransactions() g.Expect(err).ShouldNot(gomega.HaveOccurred(), "error getting CL Node transactions") - l.Debug().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") + l.Info().Int("Number of TXs", len(clNodeTxs.Data)).Msg("BHS Node txs") g.Expect(len(clNodeTxs.Data)).Should(gomega.BeNumerically("==", 1), "Expected 1 tx posted by BHS Node, but found %d", len(clNodeTxs.Data)) txHash = clNodeTxs.Data[0].Attributes.Hash }, "2m", "1s").Should(gomega.Succeed()) @@ -1556,7 +1559,7 @@ func TestVRFV2PlusWithBHF(t *testing.T) { status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) - l.Debug().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") + l.Info().Bool("Fulfilment Status", status.Fulfilled).Msg("Random Words Request Fulfilment Status") clNodeTxs, _, err := nodeTypeToNodeMap[vrfcommon.BHF].CLNode.API.ReadTransactions() require.NoError(t, err, "error fetching txns from BHF node") From 4279beca80af207f4c68a33495e73f605976c912 Mon Sep 17 00:00:00 2001 From: Patrick Date: Thu, 18 Apr 2024 21:56:45 -0400 Subject: [PATCH 13/26] bumping wsrpc to latest (#12665) * bumping wsrpc to latest * chore/bump_wsrpc: fixing TestTelemetryIngressClient_Send_HappyPath * WIP: debugging LLO timeout * Fixed LLO test * lint * refactoring * removing dead code path * Fixed synchronization test * Adding missing test_helpers * lint * bumping to v0.8.1 release --- core/scripts/go.mod | 4 ++-- core/scripts/go.sum | 13 ++++-------- .../services/ocr2/plugins/llo/helpers_test.go | 4 ++-- .../ocr2/plugins/llo/integration_test.go | 6 +++--- .../ocr2/plugins/mercury/helpers_test.go | 2 +- .../telemetry_ingress_batch_client.go | 2 +- .../telemetry_ingress_client_test.go | 3 ++- core/services/telemetry/manager_test.go | 8 ++++---- core/services/telemetry/test_helpers.go | 20 +++++++++++++++++++ go.mod | 4 ++-- go.sum | 13 ++++-------- integration-tests/go.mod | 2 +- integration-tests/go.sum | 9 ++------- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 9 ++------- 15 files changed, 51 insertions(+), 50 deletions(-) create mode 100644 core/services/telemetry/test_helpers.go diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 5bffe1d7f4d..afb3248f629 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -10,7 +10,7 @@ require ( github.com/docker/go-connections v0.4.0 github.com/ethereum/go-ethereum v1.13.8 github.com/google/go-cmp v0.6.0 - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.5.0 github.com/jmoiron/sqlx v1.3.5 github.com/joho/godotenv v1.4.0 github.com/jonboulle/clockwork v0.4.0 @@ -263,7 +263,7 @@ require ( github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.6.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 30315fa38ba..449d8124317 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -161,7 +161,6 @@ github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -638,10 +637,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -1211,8 +1209,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= -github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= +github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1420,7 +1418,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1438,7 +1435,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -1780,7 +1776,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= diff --git a/core/services/ocr2/plugins/llo/helpers_test.go b/core/services/ocr2/plugins/llo/helpers_test.go index 654b524bab5..73f7fedc926 100644 --- a/core/services/ocr2/plugins/llo/helpers_test.go +++ b/core/services/ocr2/plugins/llo/helpers_test.go @@ -59,7 +59,7 @@ type request struct { } func (r request) TransmitterID() ocr2types.Account { - return ocr2types.Account(fmt.Sprintf("%x", r.pk)) + return ocr2types.Account(r.pk.String()) } type mercuryServer struct { @@ -114,7 +114,7 @@ func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.Publ t.Fatalf("[MAIN] failed to listen: %v", err) } serverURL = lis.Addr().String() - s := wsrpc.NewServer(wsrpc.Creds(srv.privKey, pubKeys)) + s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) // Register mercury implementation with the wsrpc server pb.RegisterMercuryServer(s, srv) diff --git a/core/services/ocr2/plugins/llo/integration_test.go b/core/services/ocr2/plugins/llo/integration_test.go index df77316e4dd..b6f752541f4 100644 --- a/core/services/ocr2/plugins/llo/integration_test.go +++ b/core/services/ocr2/plugins/llo/integration_test.go @@ -173,10 +173,10 @@ func TestIntegration_LLO(t *testing.T) { t.Logf("Expect report from oracle %s", o.OracleIdentity.TransmitAccount) seen[o.OracleIdentity.TransmitAccount] = make(map[llotypes.ChannelID]struct{}) } - for req := range reqs { if _, exists := seen[req.TransmitterID()]; !exists { // oracle already reported on all channels; discard + // if this test timeouts, check for expected transmitter ID continue } @@ -188,7 +188,7 @@ func TestIntegration_LLO(t *testing.T) { t.Fatalf("FAIL: expected payload %#v to contain 'report'", v) } - t.Logf("Got report from oracle %x with format: %d", req.pk, req.req.ReportFormat) + t.Logf("Got report from oracle %s with format: %d", req.pk, req.req.ReportFormat) var r datastreamsllo.Report @@ -199,7 +199,7 @@ func TestIntegration_LLO(t *testing.T) { r, err = (datastreamsllo.JSONReportCodec{}).Decode(report.([]byte)) require.NoError(t, err, "expected valid JSON") case uint32(llotypes.ReportFormatEVM): - t.Logf("Got report (EVM) from oracle %x: 0x%x", req.pk, report.([]byte)) + t.Logf("Got report (EVM) from oracle %s: 0x%x", req.pk, report.([]byte)) var err error r, err = (lloevm.ReportCodec{}).Decode(report.([]byte)) require.NoError(t, err, "expected valid EVM encoding") diff --git a/core/services/ocr2/plugins/mercury/helpers_test.go b/core/services/ocr2/plugins/mercury/helpers_test.go index 43d709453b7..fbb51557eb1 100644 --- a/core/services/ocr2/plugins/mercury/helpers_test.go +++ b/core/services/ocr2/plugins/mercury/helpers_test.go @@ -103,7 +103,7 @@ func startMercuryServer(t *testing.T, srv *mercuryServer, pubKeys []ed25519.Publ t.Fatalf("[MAIN] failed to listen: %v", err) } serverURL = lis.Addr().String() - s := wsrpc.NewServer(wsrpc.Creds(srv.privKey, pubKeys)) + s := wsrpc.NewServer(wsrpc.WithCreds(srv.privKey, pubKeys)) // Register mercury implementation with the wsrpc server pb.RegisterMercuryServer(s, srv) diff --git a/core/services/synchronization/telemetry_ingress_batch_client.go b/core/services/synchronization/telemetry_ingress_batch_client.go index b8dbb5e5d37..cade98cf606 100644 --- a/core/services/synchronization/telemetry_ingress_batch_client.go +++ b/core/services/synchronization/telemetry_ingress_batch_client.go @@ -113,7 +113,7 @@ func (tc *telemetryIngressBatchClient) Start(ctx context.Context) error { if ctx2.Err() != nil { tc.lggr.Warnw("gave up connecting to telemetry endpoint", "err", err) } else { - tc.lggr.Criticalw("telemetry endpoint dial errored unexpectedly", "err", err) + tc.lggr.Criticalw("telemetry endpoint dial errored unexpectedly", "err", err, "server pubkey", tc.serverPubKeyHex) tc.SvcErrBuffer.Append(err) } return diff --git a/core/services/synchronization/telemetry_ingress_client_test.go b/core/services/synchronization/telemetry_ingress_client_test.go index 55be107b977..e7e14eda748 100644 --- a/core/services/synchronization/telemetry_ingress_client_test.go +++ b/core/services/synchronization/telemetry_ingress_client_test.go @@ -18,6 +18,7 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/synchronization" "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/mocks" telemPb "github.com/smartcontractkit/chainlink/v2/core/services/synchronization/telem" + telem "github.com/smartcontractkit/chainlink/v2/core/services/telemetry" ) func TestTelemetryIngressClient_Send_HappyPath(t *testing.T) { @@ -33,7 +34,7 @@ func TestTelemetryIngressClient_Send_HappyPath(t *testing.T) { // Wire up the telem ingress client url := &url.URL{} - serverPubKeyHex := "33333333333" + serverPubKeyHex := telem.GetDummyKeyString() telemIngressClient := synchronization.NewTestTelemetryIngressClient(t, url, serverPubKeyHex, csaKeystore, false, telemClient) servicetest.Run(t, telemIngressClient) diff --git a/core/services/telemetry/manager_test.go b/core/services/telemetry/manager_test.go index 2d3409ba569..9b83ef08234 100644 --- a/core/services/telemetry/manager_test.go +++ b/core/services/telemetry/manager_test.go @@ -79,21 +79,21 @@ func TestNewManager(t *testing.T) { network: "NETWORK-1", chainID: "NETWORK-1-CHAINID-1", url: "http://network-1-chainID-1.test", - pubKey: "network-1-chainID-1-pub-key", + pubKey: GetDummyKeyStringWithPrefix("network-1-chainID-1-pub-key"), shouldError: false, }, { network: "NETWORK-1", chainID: "NETWORK-1-CHAINID-2", url: "http://network-1-chainID-2.test", - pubKey: "network-1-chainID-2-pub-key", + pubKey: GetDummyKeyStringWithPrefix("network-1-chainID-2-pub-key"), shouldError: false, }, { network: "NETWORK-2", chainID: "NETWORK-2-CHAINID-1", url: "http://network-2-chainID-1.test", - pubKey: "network-2-chainID-1-pub-key", + pubKey: GetDummyKeyStringWithPrefix("network-2-chainID-1-pub-key"), shouldError: false, }, { @@ -122,7 +122,7 @@ func TestNewManager(t *testing.T) { network: "NETWORK-1", chainID: "NETWORK-1-CHAINID-1", url: "http://network-1-chainID-1.test", - pubKey: "network-1-chainID-1-pub-key", + pubKey: GetDummyKeyStringWithPrefix("network-1-chainID-1-pub-key"), shouldError: true, expectedError: "endpoint already exists", }, diff --git a/core/services/telemetry/test_helpers.go b/core/services/telemetry/test_helpers.go new file mode 100644 index 00000000000..408b46666f1 --- /dev/null +++ b/core/services/telemetry/test_helpers.go @@ -0,0 +1,20 @@ +package telemetry + +import ( + "fmt" +) + +var keyString = fmt.Sprintf("%064b", 0) + +// getDummyKeyString returns a dummy key string +// satisfies the wsrpc key length constraints +func GetDummyKeyString() string { + return keyString +} + +// getDummyKeyString returns a dummy key string with the specified prefix +// satisfies the wsrpc key length constraints +func GetDummyKeyStringWithPrefix(prefix string) string { + combo := prefix + GetDummyKeyString() + return combo[:64] +} diff --git a/go.mod b/go.mod index 69b389230ac..9ad9b8c6dbe 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/go-ldap/ldap/v3 v3.4.6 github.com/go-webauthn/webauthn v0.9.4 github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b - github.com/google/uuid v1.4.0 + github.com/google/uuid v1.5.0 github.com/gorilla/securecookie v1.1.2 github.com/gorilla/sessions v1.2.2 github.com/gorilla/websocket v1.5.1 @@ -82,7 +82,7 @@ require ( github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 - github.com/smartcontractkit/wsrpc v0.7.2 + github.com/smartcontractkit/wsrpc v0.8.1 github.com/spf13/cast v1.6.0 github.com/stretchr/testify v1.9.0 github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a diff --git a/go.sum b/go.sum index ce6477a21e3..6e041744bf2 100644 --- a/go.sum +++ b/go.sum @@ -165,7 +165,6 @@ github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk= github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -629,10 +628,9 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4= -github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= +github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= @@ -1206,8 +1204,8 @@ github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235- github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= -github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= -github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= +github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1415,7 +1413,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1433,7 +1430,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= @@ -1775,7 +1771,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2042495382a..2917be8d1fc 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -384,7 +384,7 @@ require ( github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/afero v1.9.5 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c054bcc21b0..7611301476b 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -223,7 +223,6 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -826,7 +825,6 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -1551,8 +1549,8 @@ github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:D github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= github.com/smartcontractkit/wasp v0.4.5 h1:pgiXwBci2m15eo33AzspzhpNG/gxg+8QGxl+I5LpfsQ= github.com/smartcontractkit/wasp v0.4.5/go.mod h1:eVhBVLbVv0qORUlN7aR5C4aTN/lTYO3KnN1erO4ROOI= -github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= -github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= +github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1799,7 +1797,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1817,7 +1814,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= @@ -2200,7 +2196,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 882a998feec..08b3e13b646 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -374,7 +374,7 @@ require ( github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect - github.com/smartcontractkit/wsrpc v0.7.2 // indirect + github.com/smartcontractkit/wsrpc v0.8.1 // indirect github.com/soheilhy/cmux v0.1.5 // indirect github.com/sony/gobreaker v0.5.0 // indirect github.com/spf13/afero v1.9.5 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index d36ce67be0c..4bc1c163799 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -223,7 +223,6 @@ github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPn github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df h1:GSoSVRLoBaFpOOds6QyY1L8AX7uoY+Ln3BHc22W40X0= github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df/go.mod h1:hiVxq5OP2bUGBRNS3Z/bt/reCLFNbdcST6gISi1fiOM= -github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -817,7 +816,6 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3 github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -1536,8 +1534,8 @@ github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:D github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:G5Sd/yzHWf26rQ+X0nG9E0buKPqRGPMJAfk2gwCzOOw= github.com/smartcontractkit/wasp v0.4.6 h1:s6J8HgpxMHORl19nCpZPxc5jaVUQv8EXB6QjTuLXXnw= github.com/smartcontractkit/wasp v0.4.6/go.mod h1:+ViWdUf1ap6powiEiwPskpZfH/Q1sG29YoVav7zGOIo= -github.com/smartcontractkit/wsrpc v0.7.2 h1:iBXzMeg7vc5YoezIQBq896y25BARw7OKbhrb6vPbtRQ= -github.com/smartcontractkit/wsrpc v0.7.2/go.mod h1:sj7QX2NQibhkhxTfs3KOhAj/5xwgqMipTvJVSssT9i0= +github.com/smartcontractkit/wsrpc v0.8.1 h1:kk0SXLqWrWaZ3J6c7n8D0NZ2uTMBBBpG5dZZXZX8UGE= +github.com/smartcontractkit/wsrpc v0.8.1/go.mod h1:yfg8v8fPLXkb6Mcnx6Pm/snP6jJ0r5Kf762Yd1a/KpA= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -1784,7 +1782,6 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -1802,7 +1799,6 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= go4.org/netipx v0.0.0-20230125063823-8449b0a6169f h1:ketMxHg+vWm3yccyYiq+uK8D3fRmna2Fcj+awpQp84s= @@ -2187,7 +2183,6 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= From e87b83cd78595c09061c199916c4bb9145e719b7 Mon Sep 17 00:00:00 2001 From: jinhoonbang Date: Thu, 18 Apr 2024 23:14:08 -0700 Subject: [PATCH 14/26] add vrf replay logs (#12887) * add vrf replay logs * address comment * fix replay blocks logic and add logging for jobs * add changeset * fix linter * address comments --- .changeset/hungry-ways-add.md | 6 ++ core/services/blockhashstore/delegate.go | 6 ++ core/services/blockheaderfeeder/delegate.go | 6 ++ core/services/vrf/delegate.go | 14 ++++ .../vrf/v2/listener_v2_log_listener.go | 68 +++++++++++-------- 5 files changed, 73 insertions(+), 27 deletions(-) create mode 100644 .changeset/hungry-ways-add.md diff --git a/.changeset/hungry-ways-add.md b/.changeset/hungry-ways-add.md new file mode 100644 index 00000000000..657494de605 --- /dev/null +++ b/.changeset/hungry-ways-add.md @@ -0,0 +1,6 @@ +--- +"chainlink": patch +--- + +#bugfix +vrf fix replay number of blocks logic and add logging for job specs diff --git a/core/services/blockhashstore/delegate.go b/core/services/blockhashstore/delegate.go index 6bcfc26ddb6..243259a2b1a 100644 --- a/core/services/blockhashstore/delegate.go +++ b/core/services/blockhashstore/delegate.go @@ -2,6 +2,7 @@ package blockhashstore import ( "context" + "encoding/json" "fmt" "sync" "time" @@ -55,6 +56,11 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi return nil, errors.Errorf( "blockhashstore.Delegate expects a BlockhashStoreSpec to be present, got %+v", jb) } + marshalledJob, err := json.MarshalIndent(jb.BlockhashStoreSpec, "", " ") + if err != nil { + return nil, err + } + d.logger.Debugw("Creating services for job spec", "job", string(marshalledJob)) chain, err := d.legacyChains.Get(jb.BlockhashStoreSpec.EVMChainID.String()) if err != nil { diff --git a/core/services/blockheaderfeeder/delegate.go b/core/services/blockheaderfeeder/delegate.go index 07cab534af7..b750b735de8 100644 --- a/core/services/blockheaderfeeder/delegate.go +++ b/core/services/blockheaderfeeder/delegate.go @@ -2,6 +2,7 @@ package blockheaderfeeder import ( "context" + "encoding/json" "fmt" "time" @@ -52,6 +53,11 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi if jb.BlockHeaderFeederSpec == nil { return nil, errors.Errorf("Delegate expects a BlockHeaderFeederSpec to be present, got %+v", jb) } + marshalledJob, err := json.MarshalIndent(jb.BlockHeaderFeederSpec, "", " ") + if err != nil { + return nil, err + } + d.logger.Debugw("Creating services for job spec", "job", string(marshalledJob)) chain, err := d.legacyChains.Get(jb.BlockHeaderFeederSpec.EVMChainID.String()) if err != nil { diff --git a/core/services/vrf/delegate.go b/core/services/vrf/delegate.go index 84c5126afef..c5b4df3f811 100644 --- a/core/services/vrf/delegate.go +++ b/core/services/vrf/delegate.go @@ -2,6 +2,7 @@ package vrf import ( "context" + "encoding/json" "fmt" "time" @@ -74,6 +75,19 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi if jb.VRFSpec == nil || jb.PipelineSpec == nil { return nil, errors.Errorf("vrf.Delegate expects a VRFSpec and PipelineSpec to be present, got %+v", jb) } + marshalledVRFSpec, err := json.MarshalIndent(jb.VRFSpec, "", " ") + if err != nil { + return nil, err + } + marshalledPipelineSpec, err := json.MarshalIndent(jb.PipelineSpec, "", " ") + if err != nil { + return nil, err + } + d.lggr.Debugw("Creating services for job spec", + "vrfSpec", string(marshalledVRFSpec), + "pipelineSpec", string(marshalledPipelineSpec), + "keyHash", jb.VRFSpec.PublicKey.MustHash(), + ) pl, err := jb.PipelineSpec.ParsePipeline() if err != nil { return nil, err diff --git a/core/services/vrf/v2/listener_v2_log_listener.go b/core/services/vrf/v2/listener_v2_log_listener.go index 6fbe518411d..2d2c08b8590 100644 --- a/core/services/vrf/v2/listener_v2_log_listener.go +++ b/core/services/vrf/v2/listener_v2_log_listener.go @@ -129,8 +129,13 @@ func (lsn *listenerV2) initializeLastProcessedBlock(ctx context.Context) (lastPr }() numBlocksToReplay := numReplayBlocks(lsn.job.VRFSpec.RequestTimeout, lsn.chain.ID()) - ll.Debugw("running replay on log poller") - err = lp.Replay(ctx, mathutil.Max(latestBlock.FinalizedBlockNumber-numBlocksToReplay, 1)) + replayStartBlock := mathutil.Max(latestBlock.FinalizedBlockNumber-numBlocksToReplay, 1) + ll.Debugw("running replay on log poller", + "numBlocksToReplay", numBlocksToReplay, + "replayStartBlock", replayStartBlock, + "requestTimeout", lsn.job.VRFSpec.RequestTimeout, + ) + err = lp.Replay(ctx, replayStartBlock) if err != nil { return 0, fmt.Errorf("LogPoller.Replay: %w", err) } @@ -414,47 +419,56 @@ func (lsn *listenerV2) handleRequested(requested []RandomWordsRequested, request func numReplayBlocks(requestTimeout time.Duration, chainID *big.Int) int64 { var timeoutSeconds = int64(requestTimeout.Seconds()) switch chainID.String() { - case "1": // eth mainnet - case "3": // eth ropsten - case "4": // eth rinkeby - case "5": // eth goerli - case "11155111": // eth sepolia + case + "1", // eth mainnet + "3", // eth robsten + "4", // eth rinkeby + "5", // eth goerli + "11155111": // eth sepolia // block time is 12s return timeoutSeconds / 12 - case "137": // polygon mainnet - case "80001": // polygon mumbai + case + "137", // polygon mainnet + "80001", // polygon mumbai + "80002": // polygon amoy // block time is 2s return timeoutSeconds / 2 - case "56": // bsc mainnet - case "97": // bsc testnet + case + "56", // bsc mainnet + "97": // bsc testnet // block time is 2s return timeoutSeconds / 2 - case "43114": // avalanche mainnet - case "43113": // avalanche fuji + case + "43114", // avalanche mainnet + "43113": // avalanche fuji // block time is 1s return timeoutSeconds - case "250": // fantom mainnet - case "4002": // fantom testnet + case + "250", // fantom mainnet + "4002": // fantom testnet // block time is 1s return timeoutSeconds - case "42161": // arbitrum mainnet - case "421613": // arbitrum goerli - case "421614": // arbitrum sepolia + case + "42161", // arbitrum mainnet + "421613", // arbitrum goerli + "421614": // arbitrum sepolia // block time is 0.25s in the worst case return timeoutSeconds * 4 - case "10": // optimism mainnet - case "69": // optimism kovan - case "420": // optimism goerli - case "11155420": // optimism sepolia - case "8453": // base mainnet - case "84531": // base goerli - case "84532": // base sepolia + case + "10", // optimism mainnet + "69", // optimism kovan + "420", // optimism goerli + "11155420": // optimism sepolia + // block time is 2s + return timeoutSeconds / 2 + case + "8453", // base mainnet + "84531", // base goerli + "84532": // base sepolia // block time is 2s return timeoutSeconds / 2 default: // assume block time of 1s return timeoutSeconds } - // assume block time of 1s - return timeoutSeconds } From e848ae908a8af0c776329cdc1e8e43b887f450e8 Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Fri, 19 Apr 2024 11:52:37 +0300 Subject: [PATCH 15/26] VRF-1014: refactoring VRF e2e tests (#12798) * VRF-1014: refactoring VRF e2e tests * VRF-1014: fixing lint * VRF-1014: fixing lint * VRF-1014: fixing VRF v2 test * VRF-1014: making logging more DRY * VRF-1014: fixing lint * VRF-1014: fixing lint * VRF-1014: fixing sonar * VRF-1014: fixing tests * VRF-1014: fixing tests --- .../VRFCoordinatorV2PlusUpgradedVersion.sol | 385 +++++++++++------- .../vrf_v2plus_upgraded_version.go | 305 +++++++++++--- ...rapper-dependency-versions-do-not-edit.txt | 2 +- .../actions/vrf/common/logging_helpers.go | 129 ++++++ .../actions/vrf/vrfv2/contract_steps.go | 62 ++- .../actions/vrf/vrfv2/logging_helpers.go | 65 --- .../actions/vrf/vrfv2plus/contract_steps.go | 321 +++++---------- .../actions/vrf/vrfv2plus/logging_helpers.go | 172 +------- .../contracts/contract_vrf_models.go | 56 ++- .../contracts/ethereum_vrf_common.go | 124 ++++++ .../contracts/ethereum_vrfv2_contracts.go | 130 +++--- .../contracts/ethereum_vrfv2plus_contracts.go | 187 +++++++-- integration-tests/load/vrfv2/vrfv2_test.go | 5 +- integration-tests/load/vrfv2plus/gun.go | 2 +- .../load/vrfv2plus/vrfv2plus_test.go | 4 +- integration-tests/smoke/vrfv2_test.go | 30 +- integration-tests/smoke/vrfv2plus_test.go | 138 +++---- 17 files changed, 1220 insertions(+), 897 deletions(-) create mode 100644 integration-tests/actions/vrf/common/logging_helpers.go create mode 100644 integration-tests/contracts/ethereum_vrf_common.go diff --git a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol index 6599a68a96e..c88d7dec397 100644 --- a/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol +++ b/contracts/src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2PlusUpgradedVersion.sol @@ -5,6 +5,7 @@ import {BlockhashStoreInterface} from "../../interfaces/BlockhashStoreInterface. // solhint-disable-next-line no-unused-import import {IVRFCoordinatorV2Plus, IVRFSubscriptionV2Plus} from "../interfaces/IVRFCoordinatorV2Plus.sol"; import {VRF} from "../../../vrf/VRF.sol"; +import {VRFTypes} from "../../VRFTypes.sol"; import {VRFConsumerBaseV2Plus, IVRFMigratableConsumerV2Plus} from "../VRFConsumerBaseV2Plus.sol"; import {ChainSpecificUtil} from "../../../ChainSpecificUtil.sol"; import {SubscriptionAPI} from "../SubscriptionAPI.sol"; @@ -30,37 +31,39 @@ contract VRFCoordinatorV2PlusUpgradedVersion is // 5k is plenty for an EXTCODESIZE call (2600) + warm CALL (100) // and some arithmetic operations. uint256 private constant GAS_FOR_CALL_EXACT_CHECK = 5_000; + // upper bound limit for premium percentages to make sure fee calculations don't overflow + uint8 private constant PREMIUM_PERCENTAGE_MAX = 155; error InvalidRequestConfirmations(uint16 have, uint16 min, uint16 max); error GasLimitTooBig(uint32 have, uint32 want); error NumWordsTooBig(uint32 have, uint32 want); + error MsgDataTooBig(uint256 have, uint32 max); error ProvingKeyAlreadyRegistered(bytes32 keyHash); error NoSuchProvingKey(bytes32 keyHash); error InvalidLinkWeiPrice(int256 linkWei); + error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); + error InvalidPremiumPercentage(uint8 premiumPercentage, uint8 max); error NoCorrespondingRequest(); error IncorrectCommitment(); error BlockhashNotInStore(uint256 blockNum); error PaymentTooLarge(); error InvalidExtraArgsTag(); + error GasPriceExceeded(uint256 gasPrice, uint256 maxGas); /// @notice emitted when version in the request doesn't match expected version error InvalidVersion(uint8 requestVersion, uint8 expectedVersion); /// @notice emitted when transferred balance (msg.value) does not match the metadata in V1MigrationData error InvalidNativeBalance(uint256 transferredValue, uint96 expectedValue); error SubscriptionIDCollisionFound(); - struct RequestCommitment { - uint64 blockNum; - uint256 subId; - uint32 callbackGasLimit; - uint32 numWords; - address sender; - bytes extraArgs; + struct ProvingKey { + bool exists; // proving key exists + uint64 maxGas; // gas lane max gas price for fulfilling requests } - mapping(bytes32 => bool) /* keyHash */ /* exists */ internal s_provingKeys; + mapping(bytes32 => ProvingKey) /* keyHash */ /* provingKey */ public s_provingKeys; bytes32[] public s_provingKeyHashes; mapping(uint256 => bytes32) /* requestID */ /* commitment */ public s_requestCommitments; + event ProvingKeyRegistered(bytes32 keyHash, uint64 maxGas); - event ProvingKeyRegistered(bytes32 keyHash); event RandomWordsRequested( bytes32 indexed keyHash, uint256 requestId, @@ -72,26 +75,18 @@ contract VRFCoordinatorV2PlusUpgradedVersion is bytes extraArgs, address indexed sender ); + event RandomWordsFulfilled( uint256 indexed requestId, uint256 outputSeed, - uint256 indexed subID, + uint256 indexed subId, uint96 payment, - bool success + bool nativePayment, + bool success, + bool onlyPremium ); - int256 internal s_fallbackWeiPerUnitLink; - - FeeConfig internal s_feeConfig; - - struct FeeConfig { - // Flat fee charged per fulfillment in millionths of link - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeLinkPPM; - // Flat fee charged per fulfillment in millionths of native. - // So fee range is [0, 2^32/10^6]. - uint32 fulfillmentFlatFeeNativePPM; - } + int256 public s_fallbackWeiPerUnitLink; event ConfigSet( uint16 minimumRequestConfirmations, @@ -99,26 +94,30 @@ contract VRFCoordinatorV2PlusUpgradedVersion is uint32 stalenessSeconds, uint32 gasAfterPaymentCalculation, int256 fallbackWeiPerUnitLink, + uint32 fulfillmentFlatFeeNativePPM, + uint32 fulfillmentFlatFeeLinkDiscountPPM, uint8 nativePremiumPercentage, uint8 linkPremiumPercentage ); + event FallbackWeiPerUnitLinkUsed(uint256 requestId, int256 fallbackWeiPerUnitLink); + constructor(address blockhashStore) SubscriptionAPI() { BLOCKHASH_STORE = BlockhashStoreInterface(blockhashStore); } /** - * @notice Registers a proving key to an oracle. + * @notice Registers a proving key to. * @param publicProvingKey key that oracle can use to submit vrf fulfillments */ - function registerProvingKey(uint256[2] calldata publicProvingKey) external onlyOwner { + function registerProvingKey(uint256[2] calldata publicProvingKey, uint64 maxGas) external onlyOwner { bytes32 kh = hashOfKey(publicProvingKey); - if (s_provingKeys[kh]) { + if (s_provingKeys[kh].exists) { revert ProvingKeyAlreadyRegistered(kh); } - s_provingKeys[kh] = true; + s_provingKeys[kh] = ProvingKey({exists: true, maxGas: maxGas}); s_provingKeyHashes.push(kh); - emit ProvingKeyRegistered(kh); + emit ProvingKeyRegistered(kh, maxGas); } /** @@ -136,6 +135,8 @@ contract VRFCoordinatorV2PlusUpgradedVersion is * @param stalenessSeconds if the native/link feed is more stale then this, use the fallback price * @param gasAfterPaymentCalculation gas used in doing accounting after completing the gas measurement * @param fallbackWeiPerUnitLink fallback native/link price in the case of a stale feed + * @param fulfillmentFlatFeeNativePPM flat fee in native for native payment + * @param fulfillmentFlatFeeLinkDiscountPPM flat fee discount for link payment in native * @param nativePremiumPercentage native premium percentage * @param linkPremiumPercentage link premium percentage */ @@ -160,6 +161,15 @@ contract VRFCoordinatorV2PlusUpgradedVersion is if (fallbackWeiPerUnitLink <= 0) { revert InvalidLinkWeiPrice(fallbackWeiPerUnitLink); } + if (fulfillmentFlatFeeLinkDiscountPPM > fulfillmentFlatFeeNativePPM) { + revert LinkDiscountTooHigh(fulfillmentFlatFeeLinkDiscountPPM, fulfillmentFlatFeeNativePPM); + } + if (nativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(nativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } + if (linkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(linkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + } s_config = Config({ minimumRequestConfirmations: minimumRequestConfirmations, maxGasLimit: maxGasLimit, @@ -178,6 +188,8 @@ contract VRFCoordinatorV2PlusUpgradedVersion is stalenessSeconds, gasAfterPaymentCalculation, fallbackWeiPerUnitLink, + fulfillmentFlatFeeNativePPM, + fulfillmentFlatFeeLinkDiscountPPM, nativePremiumPercentage, linkPremiumPercentage ); @@ -232,18 +244,18 @@ contract VRFCoordinatorV2PlusUpgradedVersion is */ function requestRandomWords( VRFV2PlusClient.RandomWordsRequest calldata req - ) external override nonReentrant returns (uint256) { + ) external override nonReentrant returns (uint256 requestId) { // Input validation using the subscription storage. - if (s_subscriptionConfigs[req.subId].owner == address(0)) { + uint256 subId = req.subId; + if (s_subscriptionConfigs[subId].owner == address(0)) { revert InvalidSubscription(); } // Its important to ensure that the consumer is in fact who they say they // are, otherwise they could use someone else's subscription balance. - // A nonce of 0 indicates consumer is not allocated to the sub. mapping(uint256 => ConsumerConfig) storage consumerConfigs = s_consumers[msg.sender]; - ConsumerConfig memory consumerConfig = consumerConfigs[req.subId]; + ConsumerConfig memory consumerConfig = consumerConfigs[subId]; if (!consumerConfig.active) { - revert InvalidConsumer(req.subId, msg.sender); + revert InvalidConsumer(subId, msg.sender); } // Input validation using the config storage word. if ( @@ -265,19 +277,21 @@ contract VRFCoordinatorV2PlusUpgradedVersion is if (req.numWords > MAX_NUM_WORDS) { revert NumWordsTooBig(req.numWords, MAX_NUM_WORDS); } + // Note we do not check whether the keyHash is valid to save gas. // The consequence for users is that they can send requests // for invalid keyHashes which will simply not be fulfilled. ++consumerConfig.nonce; - (uint256 requestId, uint256 preSeed) = _computeRequestId(req.keyHash, msg.sender, req.subId, consumerConfig.nonce); + ++consumerConfig.pendingReqCount; + uint256 preSeed; + (requestId, preSeed) = _computeRequestId(req.keyHash, msg.sender, subId, consumerConfig.nonce); - VRFV2PlusClient.ExtraArgsV1 memory extraArgs = _fromBytes(req.extraArgs); - bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(extraArgs); + bytes memory extraArgsBytes = VRFV2PlusClient._argsToBytes(_fromBytes(req.extraArgs)); s_requestCommitments[requestId] = keccak256( abi.encode( requestId, ChainSpecificUtil._getBlockNumber(), - req.subId, + subId, req.callbackGasLimit, req.numWords, msg.sender, @@ -288,14 +302,14 @@ contract VRFCoordinatorV2PlusUpgradedVersion is req.keyHash, requestId, preSeed, - req.subId, + subId, req.requestConfirmations, req.callbackGasLimit, req.numWords, extraArgsBytes, msg.sender ); - s_consumers[msg.sender][req.subId] = consumerConfig; + consumerConfigs[subId] = consumerConfig; return requestId; } @@ -344,18 +358,19 @@ contract VRFCoordinatorV2PlusUpgradedVersion is } struct Output { - bytes32 keyHash; + ProvingKey provingKey; uint256 requestId; uint256 randomness; } function _getRandomnessFromProof( Proof memory proof, - RequestCommitment memory rc + VRFTypes.RequestCommitmentV2Plus memory rc ) internal view returns (Output memory) { bytes32 keyHash = hashOfKey(proof.pk); + ProvingKey memory key = s_provingKeys[keyHash]; // Only registered proving keys are permitted. - if (!s_provingKeys[keyHash]) { + if (!key.exists) { revert NoSuchProvingKey(keyHash); } uint256 requestId = uint256(keccak256(abi.encode(keyHash, proof.seed))); @@ -381,179 +396,232 @@ contract VRFCoordinatorV2PlusUpgradedVersion is // The seed actually used by the VRF machinery, mixing in the blockhash uint256 actualSeed = uint256(keccak256(abi.encodePacked(proof.seed, blockHash))); uint256 randomness = VRF._randomValueFromVRFProof(proof, actualSeed); // Reverts on failure - return Output(keyHash, requestId, randomness); + return Output(key, requestId, randomness); + } + + function _getValidatedGasPrice(bool onlyPremium, uint64 gasLaneMaxGas) internal view returns (uint256 gasPrice) { + if (tx.gasprice > gasLaneMaxGas) { + if (onlyPremium) { + // if only the premium amount needs to be billed, then the premium is capped by the gas lane max + return uint256(gasLaneMaxGas); + } else { + // Ensure gas price does not exceed the gas lane max gas price + revert GasPriceExceeded(tx.gasprice, gasLaneMaxGas); + } + } + return tx.gasprice; + } + + function _deliverRandomness( + uint256 requestId, + VRFTypes.RequestCommitmentV2Plus memory rc, + uint256[] memory randomWords + ) internal returns (bool success) { + VRFConsumerBaseV2Plus v; + bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, requestId, randomWords); + // Call with explicitly the amount of callback gas requested + // Important to not let them exhaust the gas budget and avoid oracle payment. + // Do not allow any non-view/non-pure coordinator functions to be called + // during the consumers callback code via reentrancyLock. + // Note that _callWithExactGas will revert if we do not have sufficient gas + // to give the callee their requested amount. + s_config.reentrancyLock = true; + success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); + s_config.reentrancyLock = false; + return success; } /* - * @notice Fulfill a randomness request + * @notice Fulfill a randomness request. * @param proof contains the proof and randomness * @param rc request commitment pre-image, committed to at request time + * @param onlyPremium only charge premium * @return payment amount billed to the subscription * @dev simulated offchain to determine if sufficient balance is present to fulfill the request */ function fulfillRandomWords( Proof memory proof, - RequestCommitment memory rc, - bool - ) external nonReentrant returns (uint96) { + VRFTypes.RequestCommitmentV2Plus memory rc, + bool onlyPremium + ) external nonReentrant returns (uint96 payment) { uint256 startGas = gasleft(); + // fulfillRandomWords msg.data has 772 bytes and with an additional + // buffer of 32 bytes, we get 804 bytes. + /* Data size split: + * fulfillRandomWords function signature - 4 bytes + * proof - 416 bytes + * pk - 64 bytes + * gamma - 64 bytes + * c - 32 bytes + * s - 32 bytes + * seed - 32 bytes + * uWitness - 32 bytes + * cGammaWitness - 64 bytes + * sHashWitness - 64 bytes + * zInv - 32 bytes + * requestCommitment - 320 bytes + * blockNum - 32 bytes + * subId - 32 bytes + * callbackGasLimit - 32 bytes + * numWords - 32 bytes + * sender - 32 bytes + * extraArgs - 128 bytes + * onlyPremium - 32 bytes + */ + if (msg.data.length > 804) { + revert MsgDataTooBig(msg.data.length, 804); + } Output memory output = _getRandomnessFromProof(proof, rc); + uint256 gasPrice = _getValidatedGasPrice(onlyPremium, output.provingKey.maxGas); - uint256[] memory randomWords = new uint256[](rc.numWords); - for (uint256 i = 0; i < rc.numWords; i++) { - randomWords[i] = uint256(keccak256(abi.encode(output.randomness, i))); + uint256[] memory randomWords; + uint256 randomness = output.randomness; + // stack too deep error + { + uint256 numWords = rc.numWords; + randomWords = new uint256[](numWords); + for (uint256 i = 0; i < numWords; ++i) { + randomWords[i] = uint256(keccak256(abi.encode(randomness, i))); + } } delete s_requestCommitments[output.requestId]; - VRFConsumerBaseV2Plus v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomWords.selector, output.requestId, randomWords); - // Call with explicitly the amount of callback gas requested - // Important to not let them exhaust the gas budget and avoid oracle payment. - // Do not allow any non-view/non-pure coordinator functions to be called - // during the consumers callback code via reentrancyLock. - // Note that _callWithExactGas will revert if we do not have sufficient gas - // to give the callee their requested amount. - s_config.reentrancyLock = true; - bool success = _callWithExactGas(rc.callbackGasLimit, rc.sender, resp); - s_config.reentrancyLock = false; + bool success = _deliverRandomness(output.requestId, rc, randomWords); // Increment the req count for the subscription. - uint64 reqCount = s_subscriptions[rc.subId].reqCount; - s_subscriptions[rc.subId].reqCount = reqCount + 1; + ++s_subscriptions[rc.subId].reqCount; + // Decrement the pending req count for the consumer. + --s_consumers[rc.sender][rc.subId].pendingReqCount; + + bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; // stack too deep error { - bool nativePayment = uint8(rc.extraArgs[rc.extraArgs.length - 1]) == 1; - // We want to charge users exactly for how much gas they use in their callback. - // The gasAfterPaymentCalculation is meant to cover these additional operations where we - // decrement the subscription balance and increment the oracles withdrawable balance. - uint96 payment = _calculatePaymentAmount( - startGas, - s_config.gasAfterPaymentCalculation, - tx.gasprice, - nativePayment - ); - if (nativePayment) { - if (s_subscriptions[rc.subId].nativeBalance < payment) { - revert InsufficientBalance(); - } - s_subscriptions[rc.subId].nativeBalance -= payment; - s_withdrawableNative += payment; - } else { - if (s_subscriptions[rc.subId].balance < payment) { - revert InsufficientBalance(); - } - s_subscriptions[rc.subId].balance -= payment; - s_withdrawableTokens += payment; + // We want to charge users exactly for how much gas they use in their callback with + // an additional premium. If onlyPremium is true, only premium is charged without + // the gas cost. The gasAfterPaymentCalculation is meant to cover these additional + // operations where we decrement the subscription balance and increment the + // withdrawable balance. + bool isFeedStale; + (payment, isFeedStale) = _calculatePaymentAmount(startGas, gasPrice, nativePayment, onlyPremium); + if (isFeedStale) { + emit FallbackWeiPerUnitLinkUsed(output.requestId, s_fallbackWeiPerUnitLink); } + } + + _chargePayment(payment, nativePayment, rc.subId); - // Include payment in the event for tracking costs. - // event RandomWordsFulfilled(uint256 indexed requestId, uint256 outputSeed, uint96 payment, bytes extraArgs, bool success); - emit RandomWordsFulfilled(output.requestId, output.randomness, rc.subId, payment, success); + // Include payment in the event for tracking costs. + emit RandomWordsFulfilled(output.requestId, randomness, rc.subId, payment, nativePayment, success, onlyPremium); + + return payment; + } - return payment; + function _chargePayment(uint96 payment, bool nativePayment, uint256 subId) internal { + Subscription storage subcription = s_subscriptions[subId]; + if (nativePayment) { + uint96 prevBal = subcription.nativeBalance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.nativeBalance = prevBal - payment; + s_withdrawableNative += payment; + } else { + uint96 prevBal = subcription.balance; + if (prevBal < payment) { + revert InsufficientBalance(); + } + subcription.balance = prevBal - payment; + s_withdrawableTokens += payment; } } function _calculatePaymentAmount( uint256 startGas, - uint256 gasAfterPaymentCalculation, uint256 weiPerUnitGas, - bool nativePayment - ) internal view returns (uint96) { + bool nativePayment, + bool onlyPremium + ) internal view returns (uint96, bool) { if (nativePayment) { - return - _calculatePaymentAmountNative( - startGas, - gasAfterPaymentCalculation, - s_feeConfig.fulfillmentFlatFeeNativePPM, - weiPerUnitGas - ); - } - return - _calculatePaymentAmountLink( - startGas, - gasAfterPaymentCalculation, - s_feeConfig.fulfillmentFlatFeeLinkPPM, - weiPerUnitGas - ); + return (_calculatePaymentAmountNative(startGas, weiPerUnitGas, onlyPremium), false); + } + return _calculatePaymentAmountLink(startGas, weiPerUnitGas, onlyPremium); } function _calculatePaymentAmountNative( uint256 startGas, - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeePPM, - uint256 weiPerUnitGas + uint256 weiPerUnitGas, + bool onlyPremium ) internal view returns (uint96) { // Will return non-zero on chains that have this enabled uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); // calculate the payment without the premium - uint256 baseFeeWei = weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()); - // calculate the flat fee in wei - uint256 flatFeeWei = 1e12 * uint256(fulfillmentFlatFeePPM); - // return the final fee with the flat fee and l1 cost (if applicable) added - return uint96(baseFeeWei + flatFeeWei + l1CostWei); + uint256 baseFeeWei = weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()); + // calculate flat fee in native + uint256 flatFeeWei = 1e12 * uint256(s_config.fulfillmentFlatFeeNativePPM); + if (onlyPremium) { + return uint96((((l1CostWei + baseFeeWei) * (s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } else { + return uint96((((l1CostWei + baseFeeWei) * (100 + s_config.nativePremiumPercentage)) / 100) + flatFeeWei); + } } // Get the amount of gas used for fulfillment function _calculatePaymentAmountLink( uint256 startGas, - uint256 gasAfterPaymentCalculation, - uint32 fulfillmentFlatFeeLinkPPM, - uint256 weiPerUnitGas - ) internal view returns (uint96) { - int256 weiPerUnitLink; - weiPerUnitLink = _getFeedData(); + uint256 weiPerUnitGas, + bool onlyPremium + ) internal view returns (uint96, bool) { + (int256 weiPerUnitLink, bool isFeedStale) = _getFeedData(); if (weiPerUnitLink <= 0) { revert InvalidLinkWeiPrice(weiPerUnitLink); } // Will return non-zero on chains that have this enabled uint256 l1CostWei = ChainSpecificUtil._getCurrentTxL1GasFees(msg.data); // (1e18 juels/link) ((wei/gas * gas) + l1wei) / (wei/link) = juels - uint256 paymentNoFee = (1e18 * (weiPerUnitGas * (gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / + uint256 paymentNoFee = (1e18 * + (weiPerUnitGas * (s_config.gasAfterPaymentCalculation + startGas - gasleft()) + l1CostWei)) / uint256(weiPerUnitLink); - uint256 fee = 1e12 * uint256(fulfillmentFlatFeeLinkPPM); - if (paymentNoFee > (1e27 - fee)) { + // calculate the flat fee in wei + uint256 flatFeeWei = 1e12 * + uint256(s_config.fulfillmentFlatFeeNativePPM - s_config.fulfillmentFlatFeeLinkDiscountPPM); + uint256 flatFeeJuels = (1e18 * flatFeeWei) / uint256(weiPerUnitLink); + uint256 payment; + if (onlyPremium) { + payment = ((paymentNoFee * (s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } else { + payment = ((paymentNoFee * (100 + s_config.linkPremiumPercentage)) / 100 + flatFeeJuels); + } + if (payment > 1e27) { revert PaymentTooLarge(); // Payment + fee cannot be more than all of the link in existence. } - return uint96(paymentNoFee + fee); + return (uint96(payment), isFeedStale); } - function _getFeedData() private view returns (int256) { + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; uint256 timestamp; - int256 weiPerUnitLink; (, weiPerUnitLink, , timestamp, ) = LINK_NATIVE_FEED.latestRoundData(); // solhint-disable-next-line not-rely-on-time - if (staleFallback && stalenessSeconds < block.timestamp - timestamp) { + isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; + if (isFeedStale) { weiPerUnitLink = s_fallbackWeiPerUnitLink; } - return weiPerUnitLink; + return (weiPerUnitLink, isFeedStale); } - /* - * @notice Check to see if there exists a request commitment consumers - * for all consumers and keyhashes for a given sub. - * @param subId - ID of the subscription - * @return true if there exists at least one unfulfilled request for the subscription, false - * otherwise. - * @dev Looping is bounded to MAX_CONSUMERS*(number of keyhashes). - * @dev Used to disable subscription canceling while outstanding request are present. + /** + * @inheritdoc IVRFSubscriptionV2Plus */ function pendingRequestExists(uint256 subId) public view override returns (bool) { - SubscriptionConfig memory subConfig = s_subscriptionConfigs[subId]; - for (uint256 i = 0; i < subConfig.consumers.length; i++) { - for (uint256 j = 0; j < s_provingKeyHashes.length; j++) { - (uint256 reqId, ) = _computeRequestId( - s_provingKeyHashes[j], - subConfig.consumers[i], - subId, - s_consumers[subConfig.consumers[i]][subId].nonce - ); - if (s_requestCommitments[reqId] != 0) { - return true; - } + address[] storage consumers = s_subscriptionConfigs[subId].consumers; + uint256 consumersLength = consumers.length; + if (consumersLength == 0) { + return false; + } + for (uint256 i = 0; i < consumersLength; ++i) { + if (s_consumers[consumers[i]][subId].pendingReqCount > 0) { + return true; } } return false; @@ -572,7 +640,7 @@ contract VRFCoordinatorV2PlusUpgradedVersion is // Note bounded by MAX_CONSUMERS address[] memory consumers = s_subscriptionConfigs[subId].consumers; uint256 lastConsumerIndex = consumers.length - 1; - for (uint256 i = 0; i < consumers.length; i++) { + for (uint256 i = 0; i < consumers.length; ++i) { if (consumers[i] == consumer) { address last = consumers[lastConsumerIndex]; // Storage write to preserve last element @@ -582,7 +650,7 @@ contract VRFCoordinatorV2PlusUpgradedVersion is break; } } - delete s_consumers[consumer][subId]; + s_consumers[consumer][subId].active = false; emit SubscriptionConsumerRemoved(subId, consumer); } @@ -627,7 +695,8 @@ contract VRFCoordinatorV2PlusUpgradedVersion is } function _isTargetRegistered(address target) internal view returns (bool) { - for (uint256 i = 0; i < s_migrationTargets.length; i++) { + uint256 migrationTargetsLength = s_migrationTargets.length; + for (uint256 i = 0; i < migrationTargetsLength; ++i) { if (s_migrationTargets[i] == target) { return true; } @@ -647,16 +716,16 @@ contract VRFCoordinatorV2PlusUpgradedVersion is if (!_isTargetRegistered(newCoordinator)) { revert CoordinatorNotRegistered(newCoordinator); } - (uint96 balance, uint96 nativeBalance, , address owner, address[] memory consumers) = getSubscription(subId); + (uint96 balance, uint96 nativeBalance, , address subOwner, address[] memory consumers) = getSubscription(subId); // solhint-disable-next-line gas-custom-errors - require(owner == msg.sender, "Not subscription owner"); + require(subOwner == msg.sender, "Not subscription owner"); // solhint-disable-next-line gas-custom-errors require(!pendingRequestExists(subId), "Pending request exists"); V1MigrationData memory migrationData = V1MigrationData({ - fromVersion: migrationVersion(), + fromVersion: 1, subId: subId, - subOwner: owner, + subOwner: subOwner, consumers: consumers, linkBalance: balance, nativeBalance: nativeBalance @@ -674,7 +743,7 @@ contract VRFCoordinatorV2PlusUpgradedVersion is // despite the fact that we follow best practices this is still probably safest // to prevent any re-entrancy possibilities. s_config.reentrancyLock = true; - for (uint256 i = 0; i < consumers.length; i++) { + for (uint256 i = 0; i < consumers.length; ++i) { IVRFMigratableConsumerV2Plus(consumers[i]).setCoordinator(newCoordinator); } s_config.reentrancyLock = false; diff --git a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go index 79861507e14..a3ef3b83e43 100644 --- a/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go +++ b/core/gethwrappers/generated/vrf_v2plus_upgraded_version/vrf_v2plus_upgraded_version.go @@ -30,15 +30,6 @@ var ( _ = abi.ConvertType ) -type VRFCoordinatorV2PlusUpgradedVersionRequestCommitment struct { - BlockNum uint64 - SubId *big.Int - CallbackGasLimit uint32 - NumWords uint32 - Sender common.Address - ExtraArgs []byte -} - type VRFProof struct { Pk [2]*big.Int Gamma [2]*big.Int @@ -51,6 +42,15 @@ type VRFProof struct { ZInv *big.Int } +type VRFTypesRequestCommitmentV2Plus struct { + BlockNum uint64 + SubId *big.Int + CallbackGasLimit uint32 + NumWords uint32 + Sender common.Address + ExtraArgs []byte +} + type VRFV2PlusClientRandomWordsRequest struct { KeyHash [32]byte SubId *big.Int @@ -61,8 +61,8 @@ type VRFV2PlusClientRandomWordsRequest struct { } var VRFCoordinatorV2PlusUpgradedVersionMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorNotRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"transferredValue\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"expectedValue\",\"type\":\"uint96\"}],\"name\":\"InvalidNativeBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"expectedVersion\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedOwner\",\"type\":\"address\"}],\"name\":\"MustBeRequestedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIDCollisionFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subID\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"type\":\"uint256\"}],\"name\":\"SubscriptionCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"SubscriptionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"acceptSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"addConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"cancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createSubscription\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFCoordinatorV2PlusUpgradedVersion.RequestCommitment\",\"name\":\"rc\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subOwner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"}],\"name\":\"registerProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"removeConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"requestSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60a06040523480156200001157600080fd5b5060405162005e3438038062005e3483398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b608051615c61620001d3600039600081816104f401526134790152615c616000f3fe6080604052600436106101e05760003560e01c8062012291146101e5578063088070f5146102125780630ae09540146102e057806315c48b841461030257806318e3dd271461032a5780631b6b6d2314610369578063294daa49146103965780632f622e6b146103b2578063301f42e9146103d2578063405b84fa146103f257806340d6bb821461041257806341af6c871461043d57806351cff8d91461046d5780635d06b4ab1461048d57806364d51a2a146104ad57806365982744146104c2578063689c4517146104e257806372e9d5651461051657806379ba5097146105365780637bce14d11461054b5780638402595e1461056b57806386fe91c71461058b5780638da5cb5b146105ab57806395b55cfc146105c95780639b1c385e146105dc5780639d40a6fd1461060a578063a21a23e414610637578063a4c0ed361461064c578063a63e0bfb1461066c578063aa433aff1461068c578063aefb212f146106ac578063b2a7cac5146106d9578063bec4c08c146106f9578063caf70c4a14610719578063cb63179714610739578063ce3f471914610759578063d98e620e1461076c578063dac83d291461078c578063dc311dd3146107ac578063e72f6e30146107dd578063ee9d2d38146107fd578063f2fde38b1461082a575b600080fd5b3480156101f157600080fd5b506101fa61084a565b60405161020993929190614c80565b60405180910390f35b34801561021e57600080fd5b50600c546102839061ffff81169063ffffffff62010000820481169160ff600160301b8204811692600160381b8304811692600160581b8104821692600160781b8204831692600160981b83041691600160b81b8104821691600160c01b9091041689565b6040805161ffff909a168a5263ffffffff98891660208b01529615159689019690965293861660608801529185166080870152841660a08601529290921660c084015260ff91821660e08401521661010082015261012001610209565b3480156102ec57600080fd5b506103006102fb366004614cff565b6108c6565b005b34801561030e57600080fd5b5061031760c881565b60405161ffff9091168152602001610209565b34801561033657600080fd5b50600a5461035190600160601b90046001600160601b031681565b6040516001600160601b039091168152602001610209565b34801561037557600080fd5b50600254610389906001600160a01b031681565b6040516102099190614d2f565b3480156103a257600080fd5b5060405160028152602001610209565b3480156103be57600080fd5b506103006103cd366004614d43565b61090e565b3480156103de57600080fd5b506103516103ed366004614f9d565b610a5d565b3480156103fe57600080fd5b5061030061040d366004614cff565b610ef3565b34801561041e57600080fd5b506104286101f481565b60405163ffffffff9091168152602001610209565b34801561044957600080fd5b5061045d61045836600461508b565b6112b5565b6040519015158152602001610209565b34801561047957600080fd5b50610300610488366004614d43565b61145b565b34801561049957600080fd5b506103006104a8366004614d43565b6115dd565b3480156104b957600080fd5b50610317606481565b3480156104ce57600080fd5b506103006104dd3660046150a4565b611694565b3480156104ee57600080fd5b506103897f000000000000000000000000000000000000000000000000000000000000000081565b34801561052257600080fd5b50600354610389906001600160a01b031681565b34801561054257600080fd5b506103006116f4565b34801561055757600080fd5b506103006105663660046150d2565b61179e565b34801561057757600080fd5b50610300610586366004614d43565b611897565b34801561059757600080fd5b50600a54610351906001600160601b031681565b3480156105b757600080fd5b506000546001600160a01b0316610389565b6103006105d736600461508b565b6119a3565b3480156105e857600080fd5b506105fc6105f73660046150fa565b611ac4565b604051908152602001610209565b34801561061657600080fd5b5060075461062a906001600160401b031681565b6040516102099190615134565b34801561064357600080fd5b506105fc611e95565b34801561065857600080fd5b50610300610667366004615190565b612068565b34801561067857600080fd5b5061030061068736600461520e565b6121e2565b34801561069857600080fd5b506103006106a736600461508b565b6123eb565b3480156106b857600080fd5b506106cc6106c73660046152af565b612433565b604051610209919061530c565b3480156106e557600080fd5b506103006106f436600461508b565b612535565b34801561070557600080fd5b50610300610714366004614cff565b61262a565b34801561072557600080fd5b506105fc61073436600461531f565b61271c565b34801561074557600080fd5b50610300610754366004614cff565b61274c565b61030061076736600461533b565b6129b6565b34801561077857600080fd5b506105fc61078736600461508b565b612d26565b34801561079857600080fd5b506103006107a7366004614cff565b612d47565b3480156107b857600080fd5b506107cc6107c736600461508b565b612ddd565b6040516102099594939291906153b5565b3480156107e957600080fd5b506103006107f8366004614d43565b612ecb565b34801561080957600080fd5b506105fc61081836600461508b565b600f6020526000908152604090205481565b34801561083657600080fd5b50610300610845366004614d43565b613088565b600c54600e805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff169391928391908301828280156108b457602002820191906000526020600020905b8154815260200190600101908083116108a0575b50505050509050925092509250909192565b816108d08161309c565b6108d86130fd565b6108e1836112b5565b156108ff57604051631685ecdd60e31b815260040160405180910390fd5b610909838361312a565b505050565b6109166130fd565b61091e6132cf565b600b54600160601b90046001600160601b031660000361095157604051631e9acf1760e31b815260040160405180910390fd5b600b8054600160601b90046001600160601b0316908190600c6109748380615420565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b03166109bc9190615420565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610a36576040519150601f19603f3d011682016040523d82523d6000602084013e610a3b565b606091505b50509050806109095760405163950b247960e01b815260040160405180910390fd5b6000610a676130fd565b60005a90506000610a788686613322565b90506000856060015163ffffffff166001600160401b03811115610a9e57610a9e614d60565b604051908082528060200260200182016040528015610ac7578160200160208202803683370190505b50905060005b866060015163ffffffff16811015610b3e57826040015181604051602001610af6929190615440565b6040516020818303038152906040528051906020012060001c828281518110610b2157610b2161544e565b602090810291909101015280610b3681615464565b915050610acd565b50602080830180516000908152600f9092526040808320839055905190518291631fe543e360e01b91610b769190869060240161547d565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600c805460ff60301b1916600160301b1790559089015160808a0151919250600091610bdb9163ffffffff169084613582565b600c805460ff60301b1916905560208a810151600090815260069091526040902054909150600160c01b90046001600160401b0316610c1b816001615496565b6020808c0151600090815260069091526040812080546001600160401b0393909316600160c01b026001600160c01b039093169290921790915560a08b01518051610c68906001906154b6565b81518110610c7857610c7861544e565b602091010151600c5460f89190911c6001149150600090610ca9908a90600160581b900463ffffffff163a856135ce565b90508115610da1576020808d01516000908152600690915260409020546001600160601b03808316600160601b909204161015610cf957604051631e9acf1760e31b815260040160405180910390fd5b60208c81015160009081526006909152604090208054829190600c90610d30908490600160601b90046001600160601b0316615420565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b600c8282829054906101000a90046001600160601b0316610d7891906154c9565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550610e7c565b6020808d01516000908152600690915260409020546001600160601b0380831691161015610de257604051631e9acf1760e31b815260040160405180910390fd5b6020808d015160009081526006909152604081208054839290610e0f9084906001600160601b0316615420565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600b60008282829054906101000a90046001600160601b0316610e5791906154c9565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b8b6020015188602001517f49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa78a604001518488604051610ed9939291909283526001600160601b039190911660208301521515604082015260600190565b60405180910390a3985050505050505050505b9392505050565b610efb6130fd565b610f048161361d565b610f2c5780604051635428d44960e01b8152600401610f239190614d2f565b60405180910390fd5b600080600080610f3b86612ddd565b945094505093509350336001600160a01b0316826001600160a01b031614610f9e5760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b6044820152606401610f23565b610fa7866112b5565b15610fed5760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b6044820152606401610f23565b60006040518060c00160405280611002600290565b60ff168152602001888152602001846001600160a01b03168152602001838152602001866001600160601b03168152602001856001600160601b0316815250905060008160405160200161105691906154e9565b604051602081830303815290604052905061107088613686565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b038816906110a99085906004016155ae565b6000604051808303818588803b1580156110c257600080fd5b505af11580156110d6573d6000803e3d6000fd5b50506002546001600160a01b0316158015935091506110ff905057506001600160601b03861615155b156111ba5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611136908a908a906004016155c1565b6020604051808303816000875af1158015611155573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117991906155e3565b6111ba5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610f23565b600c805460ff60301b1916600160301b17905560005b8351811015611263578381815181106111eb576111eb61544e565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b815260040161121e9190614d2f565b600060405180830381600087803b15801561123857600080fd5b505af115801561124c573d6000803e3d6000fd5b50505050808061125b90615464565b9150506111d0565b50600c805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187906112a39089908b90615600565b60405180910390a15050505050505050565b6000818152600560209081526040808320815160608101835281546001600160a01b039081168252600183015416818501526002820180548451818702810187018652818152879693958601939092919083018282801561133f57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311611321575b505050505081525050905060005b8160400151518110156114515760005b600e5481101561143e576000611407600e838154811061137f5761137f61544e565b9060005260206000200154856040015185815181106113a0576113a061544e565b60200260200101518860046000896040015189815181106113c3576113c361544e565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208d825290925290205461010090046001600160401b031661382e565b506000818152600f60205260409020549091501561142b5750600195945050505050565b508061143681615464565b91505061135d565b508061144981615464565b91505061134d565b5060009392505050565b6114636130fd565b61146b6132cf565b6002546001600160a01b03166114945760405163c1f0c0a160e01b815260040160405180910390fd5b600b546001600160601b03166000036114c057604051631e9acf1760e31b815260040160405180910390fd5b600b80546001600160601b031690819060006114dc8380615420565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b03166115249190615420565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061157990859085906004016155c1565b6020604051808303816000875af1158015611598573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115bc91906155e3565b6115d957604051631e9acf1760e31b815260040160405180910390fd5b5050565b6115e56132cf565b6115ee8161361d565b1561160e578060405163ac8a27ef60e01b8152600401610f239190614d2f565b601280546001810182556000919091527fbb8a6a4669ba250d26cd7a459eca9d215f8307e33aebe50379bc5a3617ec34440180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590611689908390614d2f565b60405180910390a150565b61169c6132cf565b6002546001600160a01b0316156116c657604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b6001546001600160a01b031633146117475760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610f23565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6117a66132cf565b6040805180820182526000916117d591908490600290839083908082843760009201919091525061271c915050565b6000818152600d602052604090205490915060ff161561180b57604051634a0b8fa760e01b815260048101829052602401610f23565b6000818152600d6020526040808220805460ff19166001908117909155600e805491820181559092527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd909101829055517fc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d9061188b9083815260200190565b60405180910390a15050565b61189f6132cf565b600a544790600160601b90046001600160601b0316818111156118d95780826040516354ced18160e11b8152600401610f23929190615440565b818110156109095760006118ed82846154b6565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d806000811461193c576040519150601f19603f3d011682016040523d82523d6000602084013e611941565b606091505b50509050806119635760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c8583604051611994929190615600565b60405180910390a15050505050565b6119ab6130fd565b6000818152600560205260409020546001600160a01b03166119e057604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611a0f83856154c9565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611a5791906154c9565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e902823484611aaa9190615619565b604051611ab8929190615440565b60405180910390a25050565b6000611ace6130fd565b6020808301356000908152600590915260409020546001600160a01b0316611b0957604051630fb532db60e11b815260040160405180910390fd5b336000908152600460209081526040808320858301358452808352928190208151606081018352905460ff811615158083526001600160401b036101008304811695840195909552600160481b9091049093169181019190915290611b89578360200135336040516379bfd40160e01b8152600401610f2392919061562c565b600c5461ffff16611ba06060860160408701615643565b61ffff161080611bc3575060c8611bbd6060860160408701615643565b61ffff16115b15611bfd57611bd86060850160408601615643565b600c5460405163539c34bb60e11b8152610f23929161ffff169060c89060040161565e565b600c5462010000900463ffffffff16611c1c608086016060870161567c565b63ffffffff161115611c6257611c38608085016060860161567c565b600c54604051637aebf00f60e11b8152610f23929162010000900463ffffffff1690600401615697565b6101f4611c7560a086016080870161567c565b63ffffffff161115611caf57611c9160a085016080860161567c565b6101f46040516311ce1afb60e21b8152600401610f23929190615697565b806020018051611cbe906156ae565b6001600160401b031690526020818101516000918291611ce69188359133918a01359061382e565b90925090506000611d02611cfd60a08901896156dc565b6138b7565b90506000611d0f82613938565b905083611d1a6139a9565b60208a0135611d2f60808c0160608d0161567c565b611d3f60a08d0160808e0161567c565b3386604051602001611d579796959493929190615722565b60405160208183030381529060405280519060200120600f600086815260200190815260200160002081905550336001600160a01b0316886020013589600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e87878d6040016020810190611dce9190615643565b8e6060016020810190611de1919061567c565b8f6080016020810190611df4919061567c565b89604051611e079695949392919061576e565b60405180910390a45050336000908152600460209081526040808320898301358452825291829020855181549287015193909601516001600160401b03908116600160481b02600160481b600160881b03199190941661010002610100600160481b0319971515979097166001600160481b031990931692909217959095171617909255925050505b919050565b6000611e9f6130fd565b6007546001600160401b031633611eb76001436154b6565b6040516001600160601b0319606093841b81166020830152914060348201523090921b1660548201526001600160c01b031960c083901b16606882015260700160408051601f1981840301815291905280516020909101209150611f1c816001615496565b600780546001600160401b0319166001600160401b03928316179055604080516000808252608082018352602080830182815283850183815260608086018581528a86526006855287862093518454935191516001600160601b039182166001600160c01b031990951694909417600160601b9190921602176001600160c01b0316600160c01b9290981691909102969096179055835194850184523385528481018281528585018481528884526005835294909220855181546001600160a01b03199081166001600160a01b03928316178355935160018301805490951691161790925592518051929493919261201a9260028501920190614b8e565b5061202a91506008905084613a2a565b50827f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d3360405161205b9190614d2f565b60405180910390a2505090565b6120706130fd565b6002546001600160a01b0316331461209b576040516344b0e3c360e01b815260040160405180910390fd5b602081146120bc57604051638129bbcd60e01b815260040160405180910390fd5b60006120ca8284018461508b565b6000818152600560205260409020549091506001600160a01b031661210257604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b03169186919061212983856154c9565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b031661217191906154c9565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a8287846121c49190615619565b6040516121d2929190615440565b60405180910390a2505050505050565b6121ea6132cf565b60c861ffff8a16111561221757888960c860405163539c34bb60e11b8152600401610f239392919061565e565b6000851361223b576040516321ea67b360e11b815260048101869052602401610f23565b604080516101208101825261ffff8b1680825263ffffffff808c16602084018190526000848601528b8216606085018190528b8316608086018190528a841660a08701819052938a1660c0870181905260ff808b1660e08901819052908a16610100909801889052600c8054600160c01b90990260ff60c01b19600160b81b9093029290921661ffff60b81b19600160981b90940263ffffffff60981b19600160781b90990298909816600160781b600160b81b0319600160581b90960263ffffffff60581b19600160381b90980297909716600160301b600160781b03196201000090990265ffffffffffff19909c16909a179a909a1796909616979097179390931791909116959095179290921793909316929092179190911790556010869055517f95cb2ddab6d2297c29a4861691de69b3969c464aa4a9c44258b101ff02ff375a906123d8908b908b908b908b908b908990899061ffff97909716875263ffffffff95861660208801529385166040870152919093166060850152608084019290925260ff91821660a08401521660c082015260e00190565b60405180910390a1505050505050505050565b6123f36132cf565b6000818152600560205260409020546001600160a01b03168061242957604051630fb532db60e11b815260040160405180910390fd5b6115d9828261312a565b606060006124416008613a36565b905080841061246357604051631390f2a160e01b815260040160405180910390fd5b600061246f8486615619565b90508181118061247d575083155b6124875780612489565b815b9050600061249786836154b6565b9050806001600160401b038111156124b1576124b1614d60565b6040519080825280602002602001820160405280156124da578160200160208202803683370190505b50935060005b8181101561252a576124fd6124f58883615619565b600890613a40565b85828151811061250f5761250f61544e565b602090810291909101015261252381615464565b90506124e0565b505050505b92915050565b61253d6130fd565b6000818152600560205260409020546001600160a01b03168061257357604051630fb532db60e11b815260040160405180910390fd5b6000828152600560205260409020600101546001600160a01b031633146125ca576000828152600560205260409081902060010154905163d084e97560e01b8152610f23916001600160a01b031690600401614d2f565b600082815260056020526040908190208054336001600160a01b031991821681178355600190920180549091169055905183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c938691611ab89185916157ad565b816126348161309c565b61263c6130fd565b6001600160a01b03821660009081526004602090815260408083208684529091529020805460ff161561266f5750505050565b60008481526005602052604090206002018054606319016126a3576040516305a48e0f60e01b815260040160405180910390fd5b8154600160ff1990911681178355815490810182556000828152602090200180546001600160a01b0319166001600160a01b03861617905560405185907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e19061270d908790614d2f565b60405180910390a25050505050565b60008160405160200161272f91906157ea565b604051602081830303815290604052805190602001209050919050565b816127568161309c565b61275e6130fd565b612767836112b5565b1561278557604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b038216600090815260046020908152604080832086845290915290205460ff166127cd5782826040516379bfd40160e01b8152600401610f2392919061562c565b60008381526005602090815260408083206002018054825181850281018501909352808352919290919083018282801561283057602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612812575b5050505050905060006001825161284791906154b6565b905060005b825181101561295257846001600160a01b03168382815181106128715761287161544e565b60200260200101516001600160a01b03160361294057600083838151811061289b5761289b61544e565b60200260200101519050806005600089815260200190815260200160002060020183815481106128cd576128cd61544e565b600091825260208083209190910180546001600160a01b0319166001600160a01b039490941693909317909255888152600590915260409020600201805480612918576129186157f8565b600082815260209020810160001990810180546001600160a01b031916905501905550612952565b8061294a81615464565b91505061284c565b506001600160a01b03841660009081526004602090815260408083208884529091529081902080546001600160881b03191690555185907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a79061270d908790614d2f565b60006129c482840184615825565b9050806000015160ff166001146129fd57805160405163237d181f60e21b815260ff909116600482015260016024820152604401610f23565b8060a001516001600160601b03163414612a415760a08101516040516306acf13560e41b81523460048201526001600160601b039091166024820152604401610f23565b6020808201516000908152600590915260409020546001600160a01b031615612a7d576040516326afa43560e11b815260040160405180910390fd5b60005b816060015151811015612b7657604051806060016040528060011515815260200160006001600160401b0316815260200160006001600160401b03168152506004600084606001518481518110612ad957612ad961544e565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208684015182528352819020835181549385015194909201516001600160481b0319909316911515610100600160481b031916919091176101006001600160401b039485160217600160481b600160881b031916600160481b939092169290920217905580612b6e81615464565b915050612a80565b50604080516060808201835260808401516001600160601b03908116835260a0850151811660208085019182526000858701818152828901805183526006845288832097518854955192516001600160401b0316600160c01b026001600160c01b03938816600160601b026001600160c01b0319909716919097161794909417169390931790945584518084018652868601516001600160a01b03908116825281860184815294880151828801908152925184526005865295909220825181549087166001600160a01b0319918216178255935160018201805491909716941693909317909455925180519192612c7592600285019290910190614b8e565b5050506080810151600a8054600090612c989084906001600160601b03166154c9565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508060a00151600a600c8282829054906101000a90046001600160601b0316612ce491906154c9565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550612d2081602001516008613a2a90919063ffffffff16565b50505050565b600e8181548110612d3657600080fd5b600091825260209091200154905081565b81612d518161309c565b612d596130fd565b600083815260056020526040902060018101546001600160a01b03848116911614612d20576001810180546001600160a01b0319166001600160a01b03851617905560405184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a190612dcf90339087906157ad565b60405180910390a250505050565b600081815260056020526040812054819081906001600160a01b0316606081612e1957604051630fb532db60e11b815260040160405180910390fd5b600086815260066020908152604080832054600583529281902060020180548251818502810185019093528083526001600160601b0380861695600160601b810490911694600160c01b9091046001600160401b0316938893929091839190830182828015612eb157602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612e93575b505050505090509450945094509450945091939590929450565b612ed36132cf565b6002546001600160a01b0316612efc5760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612f2d903090600401614d2f565b602060405180830381865afa158015612f4a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6e9190615950565b600a549091506001600160601b031681811115612fa25780826040516354ced18160e11b8152600401610f23929190615440565b81811015610909576000612fb682846154b6565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612fe99087908590600401615600565b6020604051808303816000875af1158015613008573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061302c91906155e3565b61304957604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600848260405161307a929190615600565b60405180910390a150505050565b6130906132cf565b61309981613a4c565b50565b6000818152600560205260409020546001600160a01b0316806130d257604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146115d95780604051636c51fda960e11b8152600401610f239190614d2f565b600c54600160301b900460ff16156131285760405163769dd35360e11b815260040160405180910390fd5b565b60008061313684613686565b60025491935091506001600160a01b03161580159061315d57506001600160601b03821615155b156131fd5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061319d9086906001600160601b03871690600401615600565b6020604051808303816000875af11580156131bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e091906155e3565b6131fd57604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114613253576040519150601f19603f3d011682016040523d82523d6000602084013e613258565b606091505b505090508061327a5760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b03808616602083015284169181019190915285907f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c49060600161270d565b6000546001600160a01b031633146131285760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610f23565b6040805160608101825260008082526020820181905291810191909152600061334e846000015161271c565b6000818152600d602052604090205490915060ff1661338357604051631dfd6e1360e21b815260048101829052602401610f23565b600081856080015160405160200161339c929190615440565b60408051601f1981840301815291815281516020928301206000818152600f90935290822054909250908190036133e657604051631b44092560e11b815260040160405180910390fd5b845160208087015160408089015160608a015160808b015160a08c01519351613415978a979096959101615969565b60405160208183030381529060405280519060200120811461344a5760405163354a450b60e21b815260040160405180910390fd5b60006134598660000151613aef565b905080613511578551604051631d2827a760e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e9413d38916134ad9190600401615134565b602060405180830381865afa1580156134ca573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134ee9190615950565b90508061351157855160405163175dadad60e01b8152610f239190600401615134565b6000876080015182604051602001613533929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c9050600061355a8983613bbd565b6040805160608101825297885260208801969096529486019490945250929695505050505050565b60005a61138881101561359457600080fd5b6113888103905084604082048203116135ac57600080fd5b50823b6135b857600080fd5b60008083516020850160008789f1949350505050565b600081156135fb576011546135f49086908690600160201b900463ffffffff1686613c28565b9050613615565b601154613612908690869063ffffffff1686613cca565b90505b949350505050565b6000805b60125481101561367d57826001600160a01b0316601282815481106136485761364861544e565b6000918252602090912001546001600160a01b03160361366b5750600192915050565b8061367581615464565b915050613621565b50600092915050565b60008181526005602090815260408083206006909252822054600290910180546001600160601b0380841694600160601b90940416925b8181101561372857600460008483815481106136db576136db61544e565b60009182526020808320909101546001600160a01b031683528281019390935260409182018120898252909252902080546001600160881b031916905561372181615464565b90506136bd565b50600085815260056020526040812080546001600160a01b031990811682556001820180549091169055906137606002830182614bf3565b505060008581526006602052604081205561377c600886613def565b506001600160601b038416156137cf57600a80548591906000906137aa9084906001600160601b0316615420565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b6001600160601b038316156138275782600a600c8282829054906101000a90046001600160601b03166138029190615420565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b5050915091565b60408051602081018690526001600160a01b03851691810191909152606081018390526001600160401b03821660808201526000908190819060a00160408051601f198184030181529082905280516020918201209250613893918991849101615440565b60408051808303601f19018152919052805160209091012097909650945050505050565b60408051602081019091526000815260008290036138e4575060408051602081019091526000815261252f565b63125fa26760e31b6138f683856159bd565b6001600160e01b0319161461391e57604051632923fee760e11b815260040160405180910390fd5b61392b82600481866159ed565b810190610eec9190615a17565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa8260405160240161397191511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b6000466139b581613dfb565b15613a235760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156139f9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a1d9190615950565b91505090565b4391505090565b6000610eec8383613e1e565b600061252f825490565b6000610eec8383613e6d565b336001600160a01b03821603613a9e5760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610f23565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613afb81613dfb565b15613bae57610100836001600160401b0316613b156139a9565b613b1f91906154b6565b1180613b3b5750613b2e6139a9565b836001600160401b031610155b15613b495750600092915050565b6040516315a03d4160e11b8152606490632b407a8290613b6d908690600401615134565b602060405180830381865afa158015613b8a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eec9190615950565b50506001600160401b03164090565b6000613bf18360000151846020015185604001518660600151868860a001518960c001518a60e001518b6101000151613e97565b60038360200151604051602001613c09929190615a62565b60408051601f1981840301815291905280516020909101209392505050565b600080613c6b6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506140b292505050565b905060005a613c7a8888615619565b613c8491906154b6565b613c8e9085615a76565b90506000613ca763ffffffff871664e8d4a51000615a76565b905082613cb48284615619565b613cbe9190615619565b98975050505050505050565b600080613cd561417c565b905060008113613cfb576040516321ea67b360e11b815260048101829052602401610f23565b6000613d3d6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506140b292505050565b9050600082825a613d4e8b8b615619565b613d5891906154b6565b613d629088615a76565b613d6c9190615619565b613d7e90670de0b6b3a7640000615a76565b613d889190615aa3565b90506000613da163ffffffff881664e8d4a51000615a76565b9050613db881676765c793fa10079d601b1b6154b6565b821115613dd85760405163e80fa38160e01b815260040160405180910390fd5b613de28183615619565b9998505050505050505050565b6000610eec8383614238565b600061a4b1821480613e0f575062066eed82145b8061252f57505062066eee1490565b6000818152600183016020526040812054613e655750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561252f565b50600061252f565b6000826000018281548110613e8457613e8461544e565b9060005260206000200154905092915050565b613ea089614332565b613ee95760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b6044820152606401610f23565b613ef288614332565b613f365760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b6044820152606401610f23565b613f3f83614332565b613f8b5760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610f23565b613f9482614332565b613fdf5760405162461bcd60e51b815260206004820152601c60248201527b73486173685769746e657373206973206e6f74206f6e20637572766560201b6044820152606401610f23565b613feb878a88876143f5565b6140335760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b6044820152606401610f23565b600061403f8a87614509565b90506000614052898b878b86898961456d565b90506000614063838d8d8a86614680565b9050808a146140a45760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610f23565b505050505050505050505050565b6000466140be81613dfb565b1561410257606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b8a573d6000803e3d6000fd5b61410b816146c0565b1561367d57600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615c0d60489139604051602001614151929190615ab7565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613b6d91906155ae565b600c5460035460408051633fabe5a360e21b81529051600093600160381b900463ffffffff169283151592859283926001600160a01b03169163feaf968c9160048083019260a09291908290030181865afa1580156141df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142039190615afd565b509450909250849150508015614227575061421e82426154b6565b8463ffffffff16105b156136155750601054949350505050565b6000818152600183016020526040812054801561432157600061425c6001836154b6565b8554909150600090614270906001906154b6565b90508181146142d55760008660000182815481106142905761429061544e565b90600052602060002001549050808760000184815481106142b3576142b361544e565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806142e6576142e66157f8565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061252f565b600091505061252f565b5092915050565b80516000906401000003d019116143805760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b6044820152606401610f23565b60208201516401000003d019116143ce5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b6044820152606401610f23565b60208201516401000003d0199080096143ee8360005b60200201516146fa565b1492915050565b60006001600160a01b03821661443b5760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b6044820152606401610f23565b60208401516000906001161561445257601c614455565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe19918203925060009190890987516040805160008082526020909101918290529293506001916144bf91869188918790615b4d565b6020604051602081039080840390855afa1580156144e1573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b614511614c11565b61453e6001848460405160200161452a93929190615b6b565b60405160208183030381529060405261471e565b90505b61454a81614332565b61252f578051604080516020810192909252614566910161452a565b9050614541565b614575614c11565b825186516401000003d01991829006919006036145d45760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610f23565b6145df87898861476b565b6146245760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b6044820152606401610f23565b61462f84868561476b565b6146755760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b6044820152606401610f23565b613cbe868484614889565b60006002868686858760405160200161469e96959493929190615b8c565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a8214806146d257506101a482145b806146df575062aa37dc82145b806146eb575061210582145b8061252f57505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b614726614c11565b61472f8261494c565b815261474461473f8260006143e4565b614987565b6020820181905260029006600103611e90576020810180516401000003d019039052919050565b6000826000036147ab5760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b6044820152606401610f23565b835160208501516000906147c190600290615be6565b156147cd57601c6147d0565b601b5b9050600070014551231950b75fc4402da1732fc9bebe19838709604080516000808252602090910191829052919250600190614813908390869088908790615b4d565b6020604051602081039080840390855afa158015614835573d6000803e3d6000fd5b5050506020604051035190506000866040516020016148549190615bfa565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614891614c11565b8351602080860151855191860151600093849384936148b2939091906149a7565b919450925090506401000003d01985820960011461490e5760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b6044820152606401610f23565b60405180604001604052806401000003d0198061492d5761492d615a8d565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d0198110611e9057604080516020808201939093528151808203840181529082019091528051910120614954565b600061252f8260026149a06401000003d0196001615619565b901c614a87565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a08905060006149e783838585614b21565b90985090506149f888828e88614b45565b9098509050614a0988828c87614b45565b90985090506000614a1c8d878b85614b45565b9098509050614a2d88828686614b21565b9098509050614a3e88828e89614b45565b9098509050818114614a73576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614a77565b8196505b5050505050509450945094915050565b600080614a92614c2f565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614ac4614c4d565b60208160c0846005600019fa925082600003614b175760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b6044820152606401610f23565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215614be3579160200282015b82811115614be357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614bae565b50614bef929150614c6b565b5090565b50805460008255906000526020600020908101906130999190614c6b565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b80821115614bef5760008155600101614c6c565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b81811015614cd157845183529383019391830191600101614cb5565b509098975050505050505050565b6001600160a01b038116811461309957600080fd5b8035611e9081614cdf565b60008060408385031215614d1257600080fd5b823591506020830135614d2481614cdf565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215614d5557600080fd5b8135610eec81614cdf565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b0381118282101715614d9857614d98614d60565b60405290565b60405161012081016001600160401b0381118282101715614d9857614d98614d60565b604051601f8201601f191681016001600160401b0381118282101715614de957614de9614d60565b604052919050565b600082601f830112614e0257600080fd5b604080519081016001600160401b0381118282101715614e2457614e24614d60565b8060405250806040840185811115614e3b57600080fd5b845b81811015614e55578035835260209283019201614e3d565b509195945050505050565b803563ffffffff81168114611e9057600080fd5b600082601f830112614e8557600080fd5b81356001600160401b03811115614e9e57614e9e614d60565b614eb1601f8201601f1916602001614dc1565b818152846020838601011115614ec657600080fd5b816020850160208301376000918101602001919091529392505050565b600060c08284031215614ef557600080fd5b614efd614d76565b905081356001600160401b038082168214614f1757600080fd5b81835260208401356020840152614f3060408501614e60565b6040840152614f4160608501614e60565b6060840152614f5260808501614cf4565b608084015260a0840135915080821115614f6b57600080fd5b50614f7884828501614e74565b60a08301525092915050565b801515811461309957600080fd5b8035611e9081614f84565b60008060008385036101e0811215614fb457600080fd5b6101a080821215614fc457600080fd5b614fcc614d9e565b9150614fd88787614df1565b8252614fe78760408801614df1565b60208301526080860135604083015260a0860135606083015260c0860135608083015261501660e08701614cf4565b60a083015261010061502a88828901614df1565b60c084015261503d886101408901614df1565b60e0840152610180870135908301529093508401356001600160401b0381111561506657600080fd5b61507286828701614ee3565b9250506150826101c08501614f92565b90509250925092565b60006020828403121561509d57600080fd5b5035919050565b600080604083850312156150b757600080fd5b82356150c281614cdf565b91506020830135614d2481614cdf565b6000604082840312156150e457600080fd5b826040830111156150f457600080fd5b50919050565b60006020828403121561510c57600080fd5b81356001600160401b0381111561512257600080fd5b820160c08185031215610eec57600080fd5b6001600160401b0391909116815260200190565b60008083601f84011261515a57600080fd5b5081356001600160401b0381111561517157600080fd5b60208301915083602082850101111561518957600080fd5b9250929050565b600080600080606085870312156151a657600080fd5b84356151b181614cdf565b93506020850135925060408501356001600160401b038111156151d357600080fd5b6151df87828801615148565b95989497509550505050565b803561ffff81168114611e9057600080fd5b803560ff81168114611e9057600080fd5b60008060008060008060008060006101208a8c03121561522d57600080fd5b6152368a6151eb565b985061524460208b01614e60565b975061525260408b01614e60565b965061526060608b01614e60565b955060808a0135945061527560a08b01614e60565b935061528360c08b01614e60565b925061529160e08b016151fd565b91506152a06101008b016151fd565b90509295985092959850929598565b600080604083850312156152c257600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b83811015615301578151875295820195908201906001016152e5565b509495945050505050565b602081526000610eec60208301846152d1565b60006040828403121561533157600080fd5b610eec8383614df1565b6000806020838503121561534e57600080fd5b82356001600160401b0381111561536457600080fd5b61537085828601615148565b90969095509350505050565b600081518084526020808501945080840160005b838110156153015781516001600160a01b031687529582019590820190600101615390565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a0608082018190526000906153ff9083018461537c565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6001600160601b0382811682821603908082111561432b5761432b61540a565b918252602082015260400190565b634e487b7160e01b600052603260045260246000fd5b6000600182016154765761547661540a565b5060010190565b82815260406020820152600061361560408301846152d1565b6001600160401b0381811683821601908082111561432b5761432b61540a565b8181038181111561252f5761252f61540a565b6001600160601b0381811683821601908082111561432b5761432b61540a565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c0608084015261552e60e084018261537c565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b60005b83811015615579578181015183820152602001615561565b50506000910152565b6000815180845261559a81602086016020860161555e565b601f01601f19169290920160200192915050565b602081526000610eec6020830184615582565b6001600160a01b039290921682526001600160601b0316602082015260400190565b6000602082840312156155f557600080fd5b8151610eec81614f84565b6001600160a01b03929092168252602082015260400190565b8082018082111561252f5761252f61540a565b9182526001600160a01b0316602082015260400190565b60006020828403121561565557600080fd5b610eec826151eb565b61ffff93841681529183166020830152909116604082015260600190565b60006020828403121561568e57600080fd5b610eec82614e60565b63ffffffff92831681529116602082015260400190565b60006001600160401b038281166002600160401b031981016156d2576156d261540a565b6001019392505050565b6000808335601e198436030181126156f357600080fd5b8301803591506001600160401b0382111561570d57600080fd5b60200191503681900382131561518957600080fd5b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c08201819052600090613de290830184615582565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a0830152613cbe60c0830184615582565b6001600160a01b0392831681529116602082015260400190565b8060005b6002811015612d205781518452602093840193909101906001016157cb565b6040810161252f82846157c7565b634e487b7160e01b600052603160045260246000fd5b80356001600160601b0381168114611e9057600080fd5b6000602080838503121561583857600080fd5b82356001600160401b038082111561584f57600080fd5b9084019060c0828703121561586357600080fd5b61586b614d76565b615874836151fd565b81528383013584820152604083013561588c81614cdf565b60408201526060830135828111156158a357600080fd5b8301601f810188136158b457600080fd5b8035838111156158c6576158c6614d60565b8060051b93506158d7868501614dc1565b818152938201860193868101908a8611156158f157600080fd5b928701925b8584101561591b578335925061590b83614cdf565b82825292870192908701906158f6565b6060850152506159309150506080840161580e565b608082015261594160a0840161580e565b60a08201529695505050505050565b60006020828403121561596257600080fd5b5051919050565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c08201819052600090613de290830184615582565b6001600160e01b031981358181169160048510156159e55780818660040360031b1b83161692505b505092915050565b600080858511156159fd57600080fd5b83861115615a0a57600080fd5b5050820193919092039150565b600060208284031215615a2957600080fd5b604051602081016001600160401b0381118282101715615a4b57615a4b614d60565b6040528235615a5981614f84565b81529392505050565b82815260608101610eec60208301846157c7565b808202811582820484141761252f5761252f61540a565b634e487b7160e01b600052601260045260246000fd5b600082615ab257615ab2615a8d565b500490565b60008351615ac981846020880161555e565b835190830190615add81836020880161555e565b01949350505050565b80516001600160501b0381168114611e9057600080fd5b600080600080600060a08688031215615b1557600080fd5b615b1e86615ae6565b9450602086015193506040860151925060608601519150615b4160808701615ae6565b90509295509295909350565b93845260ff9290921660208401526040830152606082015260800190565b838152615b7b60208201846157c7565b606081019190915260800192915050565b868152615b9c60208201876157c7565b615ba960608201866157c7565b615bb660a08201856157c7565b615bc360e08201846157c7565b60609190911b6001600160601b0319166101208201526101340195945050505050565b600082615bf557615bf5615a8d565b500690565b615c0481836157c7565b60400191905056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"blockhashStore\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"internalBalance\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"externalBalance\",\"type\":\"uint256\"}],\"name\":\"BalanceInvariantViolated\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"blockNum\",\"type\":\"uint256\"}],\"name\":\"BlockhashNotInStore\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorNotRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToSendNative\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"GasLimitTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gasPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxGas\",\"type\":\"uint256\"}],\"name\":\"GasPriceExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncorrectCommitment\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IndexOutOfRange\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"InvalidConsumer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidExtraArgsTag\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"int256\",\"name\":\"linkWei\",\"type\":\"int256\"}],\"name\":\"InvalidLinkWeiPrice\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"transferredValue\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"expectedValue\",\"type\":\"uint96\"}],\"name\":\"InvalidNativeBalance\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"max\",\"type\":\"uint8\"}],\"name\":\"InvalidPremiumPercentage\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"have\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"min\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"max\",\"type\":\"uint16\"}],\"name\":\"InvalidRequestConfirmations\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidSubscription\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"requestVersion\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"expectedVersion\",\"type\":\"uint8\"}],\"name\":\"InvalidVersion\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkAlreadySet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"flatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"flatFeeNativePPM\",\"type\":\"uint32\"}],\"name\":\"LinkDiscountTooHigh\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LinkNotSet\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"have\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"max\",\"type\":\"uint32\"}],\"name\":\"MsgDataTooBig\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"proposedOwner\",\"type\":\"address\"}],\"name\":\"MustBeRequestedOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"MustBeSubOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoCorrespondingRequest\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"NoSuchProvingKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"have\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"want\",\"type\":\"uint32\"}],\"name\":\"NumWordsTooBig\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PaymentTooLarge\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"PendingRequestExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"}],\"name\":\"ProvingKeyAlreadyRegistered\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"Reentrant\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIDCollisionFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TooManyConsumers\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"coordinatorAddress\",\"type\":\"address\"}],\"name\":\"CoordinatorRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"name\":\"FallbackWeiPerUnitLinkUsed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"FundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"MigrationCompleted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeFundsRecovered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"name\":\"ProvingKeyRegistered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"outputSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"nativePayment\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"onlyPremium\",\"type\":\"bool\"}],\"name\":\"RandomWordsFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"preSeed\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RandomWordsRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountLink\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountNative\",\"type\":\"uint256\"}],\"name\":\"SubscriptionCanceled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"SubscriptionConsumerRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"SubscriptionCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldNativeBalance\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newNativeBalance\",\"type\":\"uint256\"}],\"name\":\"SubscriptionFundedWithNative\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"SubscriptionOwnerTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"BLOCKHASH_STORE\",\"outputs\":[{\"internalType\":\"contractBlockhashStoreInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"LINK_NATIVE_FEED\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_CONSUMERS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_NUM_WORDS\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MAX_REQUEST_CONFIRMATIONS\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"acceptSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"addConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"cancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"createSubscription\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256[2]\",\"name\":\"pk\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"gamma\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"c\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"s\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seed\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"uWitness\",\"type\":\"address\"},{\"internalType\":\"uint256[2]\",\"name\":\"cGammaWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256[2]\",\"name\":\"sHashWitness\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint256\",\"name\":\"zInv\",\"type\":\"uint256\"}],\"internalType\":\"structVRF.Proof\",\"name\":\"proof\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"blockNum\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFTypes.RequestCommitmentV2Plus\",\"name\":\"rc\",\"type\":\"tuple\"},{\"internalType\":\"bool\",\"name\":\"onlyPremium\",\"type\":\"bool\"}],\"name\":\"fulfillRandomWords\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"payment\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"fundSubscriptionWithNative\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"startIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxCount\",\"type\":\"uint256\"}],\"name\":\"getActiveSubscriptionIds\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"ids\",\"type\":\"uint256[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRequestConfig\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"},{\"internalType\":\"bytes32[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"getSubscription\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"balance\",\"type\":\"uint96\"},{\"internalType\":\"uint96\",\"name\":\"nativeBalance\",\"type\":\"uint96\"},{\"internalType\":\"uint64\",\"name\":\"reqCount\",\"type\":\"uint64\"},{\"internalType\":\"address\",\"name\":\"subOwner\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"consumers\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicKey\",\"type\":\"uint256[2]\"}],\"name\":\"hashOfKey\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newCoordinator\",\"type\":\"address\"}],\"name\":\"migrate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"migrationVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"version\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"encodedData\",\"type\":\"bytes\"}],\"name\":\"onMigration\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"onTokenTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"ownerCancelSubscription\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"}],\"name\":\"pendingRequestExists\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"recoverNativeFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"}],\"name\":\"registerMigratableCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256[2]\",\"name\":\"publicProvingKey\",\"type\":\"uint256[2]\"},{\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"name\":\"registerProvingKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"removeConsumer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"uint16\",\"name\":\"requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"internalType\":\"structVRFV2PlusClient.RandomWordsRequest\",\"name\":\"req\",\"type\":\"tuple\"}],\"name\":\"requestRandomWords\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"subId\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"requestSubscriptionOwnerTransfer\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"bool\",\"name\":\"reentrancyLock\",\"type\":\"bool\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_currentSubNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fallbackWeiPerUnitLink\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_provingKeyHashes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"s_provingKeys\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"uint64\",\"name\":\"maxGas\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_requestCommitments\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_totalNativeBalance\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"minimumRequestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"maxGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"gasAfterPaymentCalculation\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"nativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"linkPremiumPercentage\",\"type\":\"uint8\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLINKAndLINKNativeFeed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60a06040523480156200001157600080fd5b506040516200613f3803806200613f83398101604081905262000034916200017e565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000d3565b5050506001600160a01b0316608052620001b0565b336001600160a01b038216036200012d5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6000602082840312156200019157600080fd5b81516001600160a01b0381168114620001a957600080fd5b9392505050565b608051615f6c620001d36000396000818161052e01526133610152615f6c6000f3fe6080604052600436106101f65760003560e01c8062012291146101fb578063043bd6ae14610228578063088070f51461024c5780630ae095401461031a57806315c48b841461033c57806318e3dd27146103645780631b6b6d23146103a3578063294daa49146103d05780632f622e6b146103ec578063301f42e91461040c578063405b84fa1461042c57806340d6bb821461044c57806341af6c871461047757806351cff8d9146104a75780635d06b4ab146104c757806364d51a2a146104e757806365982744146104fc578063689c45171461051c57806372e9d5651461055057806379ba5097146105705780637a5a2aef146105855780638402595e146105a557806386fe91c7146105c55780638da5cb5b146105e557806395b55cfc146106035780639b1c385e146106165780639d40a6fd14610636578063a21a23e414610663578063a4c0ed3614610678578063a63e0bfb14610698578063aa433aff146106b8578063aefb212f146106d8578063b2a7cac514610705578063bec4c08c14610725578063caf70c4a14610745578063cb63179714610765578063ce3f471914610785578063d98e620e14610798578063da2f2610146107b8578063dac83d2914610817578063dc311dd314610837578063e72f6e3014610868578063ee9d2d3814610888578063f2fde38b146108b5575b600080fd5b34801561020757600080fd5b506102106108d5565b60405161021f93929190614eeb565b60405180910390f35b34801561023457600080fd5b5061023e60105481565b60405190815260200161021f565b34801561025857600080fd5b50600c546102bd9061ffff81169063ffffffff62010000820481169160ff600160301b8204811692600160381b8304811692600160581b8104821692600160781b8204831692600160981b83041691600160b81b8104821691600160c01b9091041689565b6040805161ffff909a168a5263ffffffff98891660208b01529615159689019690965293861660608801529185166080870152841660a08601529290921660c084015260ff91821660e0840152166101008201526101200161021f565b34801561032657600080fd5b5061033a610335366004614f6a565b610951565b005b34801561034857600080fd5b5061035160c881565b60405161ffff909116815260200161021f565b34801561037057600080fd5b50600a5461038b90600160601b90046001600160601b031681565b6040516001600160601b03909116815260200161021f565b3480156103af57600080fd5b506002546103c3906001600160a01b031681565b60405161021f9190614f9a565b3480156103dc57600080fd5b506040516002815260200161021f565b3480156103f857600080fd5b5061033a610407366004614fae565b610999565b34801561041857600080fd5b5061038b6104273660046151fd565b610ae8565b34801561043857600080fd5b5061033a610447366004614f6a565b610e02565b34801561045857600080fd5b506104626101f481565b60405163ffffffff909116815260200161021f565b34801561048357600080fd5b506104976104923660046152eb565b6111a5565b604051901515815260200161021f565b3480156104b357600080fd5b5061033a6104c2366004614fae565b611259565b3480156104d357600080fd5b5061033a6104e2366004614fae565b6113db565b3480156104f357600080fd5b50610351606481565b34801561050857600080fd5b5061033a610517366004615304565b611492565b34801561052857600080fd5b506103c37f000000000000000000000000000000000000000000000000000000000000000081565b34801561055c57600080fd5b506003546103c3906001600160a01b031681565b34801561057c57600080fd5b5061033a6114f2565b34801561059157600080fd5b5061033a6105a0366004615332565b61159c565b3480156105b157600080fd5b5061033a6105c0366004614fae565b6116d8565b3480156105d157600080fd5b50600a5461038b906001600160601b031681565b3480156105f157600080fd5b506000546001600160a01b03166103c3565b61033a6106113660046152eb565b6117e4565b34801561062257600080fd5b5061023e61063136600461536c565b611905565b34801561064257600080fd5b50600754610656906001600160401b031681565b60405161021f91906153a6565b34801561066f57600080fd5b5061023e611cbf565b34801561068457600080fd5b5061033a610693366004615402565b611e92565b3480156106a457600080fd5b5061033a6106b3366004615480565b61200c565b3480156106c457600080fd5b5061033a6106d33660046152eb565b6122ae565b3480156106e457600080fd5b506106f86106f3366004615521565b6122f6565b60405161021f919061557e565b34801561071157600080fd5b5061033a6107203660046152eb565b6123f8565b34801561073157600080fd5b5061033a610740366004614f6a565b6124ed565b34801561075157600080fd5b5061023e610760366004615591565b6125df565b34801561077157600080fd5b5061033a610780366004614f6a565b61260f565b61033a6107933660046155ad565b612871565b3480156107a457600080fd5b5061023e6107b33660046152eb565b612bd8565b3480156107c457600080fd5b506107f86107d33660046152eb565b600d6020526000908152604090205460ff81169061010090046001600160401b031682565b6040805192151583526001600160401b0390911660208301520161021f565b34801561082357600080fd5b5061033a610832366004614f6a565b612bf9565b34801561084357600080fd5b506108576108523660046152eb565b612c8f565b60405161021f959493929190615627565b34801561087457600080fd5b5061033a610883366004614fae565b612d7d565b34801561089457600080fd5b5061023e6108a33660046152eb565b600f6020526000908152604090205481565b3480156108c157600080fd5b5061033a6108d0366004614fae565b612f3a565b600c54600e805460408051602080840282018101909252828152600094859460609461ffff8316946201000090930463ffffffff1693919283919083018282801561093f57602002820191906000526020600020905b81548152602001906001019080831161092b575b50505050509050925092509250909192565b8161095b81612f4e565b610963612faf565b61096c836111a5565b1561098a57604051631685ecdd60e31b815260040160405180910390fd5b6109948383612fdc565b505050565b6109a1612faf565b6109a9613181565b600b54600160601b90046001600160601b03166000036109dc57604051631e9acf1760e31b815260040160405180910390fd5b600b8054600160601b90046001600160601b0316908190600c6109ff8380615692565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a600c8282829054906101000a90046001600160601b0316610a479190615692565b92506101000a8154816001600160601b0302191690836001600160601b031602179055506000826001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114610ac1576040519150601f19603f3d011682016040523d82523d6000602084013e610ac6565b606091505b50509050806109945760405163950b247960e01b815260040160405180910390fd5b6000610af2612faf565b60005a9050610324361115610b2957604051630f28961b60e01b815236600482015261032460248201526044015b60405180910390fd5b6000610b3586866131d4565b90506000610b4b8583600001516020015161346b565b60408301516060888101519293509163ffffffff16806001600160401b03811115610b7857610b78614fcb565b604051908082528060200260200182016040528015610ba1578160200160208202803683370190505b50925060005b81811015610c08578281604051602001610bc29291906156b2565b6040516020818303038152906040528051906020012060001c848281518110610bed57610bed6156c0565b6020908102919091010152610c01816156d6565b9050610ba7565b5050602080850180516000908152600f9092526040822082905551610c2e908a856134b9565b60208a8101516000908152600690915260409020805491925090601890610c6490600160c01b90046001600160401b03166156ef565b82546101009290920a6001600160401b0381810219909316918316021790915560808a01516001600160a01b03166000908152600460209081526040808320828e01518452909152902080549091600991610cc791600160481b9091041661571d565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555060008960a0015160018b60a0015151610d049190615740565b81518110610d1457610d146156c0565b60209101015160f81c60011490506000610d308887848d613554565b90995090508015610d7b577f6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a8760200151601054604051610d729291906156b2565b60405180910390a15b50610d8b88828c6020015161358c565b6020808b015187820151604080518781526001600160601b038d16948101949094528415159084015284151560608401528b1515608084015290917faeb4b4786571e184246d39587f659abf0e26f41f6a3358692250382c0cdb47b79060a00160405180910390a3505050505050505b9392505050565b610e0a612faf565b610e13816136df565b610e325780604051635428d44960e01b8152600401610b209190614f9a565b600080600080610e4186612c8f565b945094505093509350336001600160a01b0316826001600160a01b031614610ea45760405162461bcd60e51b81526020600482015260166024820152752737ba1039bab139b1b934b83a34b7b71037bbb732b960511b6044820152606401610b20565b610ead866111a5565b15610ef35760405162461bcd60e51b815260206004820152601660248201527550656e64696e6720726571756573742065786973747360501b6044820152606401610b20565b6040805160c0810182526001815260208082018990526001600160a01b03851682840152606082018490526001600160601b038088166080840152861660a083015291519091600091610f4891849101615753565b6040516020818303038152906040529050610f628861374a565b505060405163ce3f471960e01b81526001600160a01b0388169063ce3f4719906001600160601b03881690610f9b908590600401615818565b6000604051808303818588803b158015610fb457600080fd5b505af1158015610fc8573d6000803e3d6000fd5b50506002546001600160a01b031615801593509150610ff1905057506001600160601b03861615155b156110ac5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611028908a908a9060040161582b565b6020604051808303816000875af1158015611047573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061106b919061584d565b6110ac5760405162461bcd60e51b8152602060048201526012602482015271696e73756666696369656e742066756e647360701b6044820152606401610b20565b600c805460ff60301b1916600160301b17905560005b8351811015611153578381815181106110dd576110dd6156c0565b60200260200101516001600160a01b0316638ea98117896040518263ffffffff1660e01b81526004016111109190614f9a565b600060405180830381600087803b15801561112a57600080fd5b505af115801561113e573d6000803e3d6000fd5b505050508061114c906156d6565b90506110c2565b50600c805460ff60301b191690556040517fd63ca8cb945956747ee69bfdc3ea754c24a4caf7418db70e46052f7850be4187906111939089908b9061586a565b60405180910390a15050505050505050565b600081815260056020526040812060020180548083036111c9575060009392505050565b60005b8181101561124e576000600460008584815481106111ec576111ec6156c0565b60009182526020808320909101546001600160a01b0316835282810193909352604091820181208982529092529020546001600160401b03600160481b90910416111561123e57506001949350505050565b611247816156d6565b90506111cc565b506000949350505050565b611261612faf565b611269613181565b6002546001600160a01b03166112925760405163c1f0c0a160e01b815260040160405180910390fd5b600b546001600160601b03166000036112be57604051631e9acf1760e31b815260040160405180910390fd5b600b80546001600160601b031690819060006112da8380615692565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555080600a60008282829054906101000a90046001600160601b03166113229190615692565b82546001600160601b039182166101009390930a92830291909202199091161790555060025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb90611377908590859060040161582b565b6020604051808303816000875af1158015611396573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ba919061584d565b6113d757604051631e9acf1760e31b815260040160405180910390fd5b5050565b6113e3613181565b6113ec816136df565b1561140c578060405163ac8a27ef60e01b8152600401610b209190614f9a565b601180546001810182556000919091527f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c680180546001600160a01b0319166001600160a01b0383161790556040517fb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af0162590611487908390614f9a565b60405180910390a150565b61149a613181565b6002546001600160a01b0316156114c457604051631688c53760e11b815260040160405180910390fd5b600280546001600160a01b039384166001600160a01b03199182161790915560038054929093169116179055565b6001546001600160a01b031633146115455760405162461bcd60e51b815260206004820152601660248201527526bab9ba10313290383937b837b9b2b21037bbb732b960511b6044820152606401610b20565b60008054336001600160a01b0319808316821784556001805490911690556040516001600160a01b0390921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6115a4613181565b6040805180820182526000916115d39190859060029083908390808284376000920191909152506125df915050565b6000818152600d602052604090205490915060ff161561160957604051634a0b8fa760e01b815260048101829052602401610b20565b60408051808201825260018082526001600160401b0385811660208085019182526000878152600d9091528581209451855492516001600160481b0319909316901515610100600160481b03191617610100929093169190910291909117909255600e805491820181559091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd01829055517f9b911b2c240bfbef3b6a8f7ed6ee321d1258bb2a3fe6becab52ac1cd3210afd3906116cb9083908590615883565b60405180910390a1505050565b6116e0613181565b600a544790600160601b90046001600160601b03168181111561171a5780826040516354ced18160e11b8152600401610b209291906156b2565b8181101561099457600061172e8284615740565b90506000846001600160a01b03168260405160006040518083038185875af1925050503d806000811461177d576040519150601f19603f3d011682016040523d82523d6000602084013e611782565b606091505b50509050806117a45760405163950b247960e01b815260040160405180910390fd5b7f4aed7c8eed0496c8c19ea2681fcca25741c1602342e38b045d9f1e8e905d2e9c85836040516117d592919061586a565b60405180910390a15050505050565b6117ec612faf565b6000818152600560205260409020546001600160a01b031661182157604051630fb532db60e11b815260040160405180910390fd5b60008181526006602052604090208054600160601b90046001600160601b0316903490600c611850838561589a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555034600a600c8282829054906101000a90046001600160601b0316611898919061589a565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f7603b205d03651ee812f803fccde89f1012e545a9c99f0abfea9cedd0fd8e9028234846118eb91906158ba565b6040516118f99291906156b2565b60405180910390a25050565b600061190f612faf565b602080830135600081815260059092526040909120546001600160a01b031661194b57604051630fb532db60e11b815260040160405180910390fd5b336000908152600460209081526040808320848452808352928190208151606081018352905460ff811615158083526001600160401b036101008304811695840195909552600160481b90910490931691810191909152906119c45782336040516379bfd40160e01b8152600401610b209291906158cd565b600c5461ffff166119db60608701604088016158e4565b61ffff1610806119fe575060c86119f860608701604088016158e4565b61ffff16115b15611a3857611a1360608601604087016158e4565b600c5460405163539c34bb60e11b8152610b20929161ffff169060c8906004016158ff565b600c5462010000900463ffffffff16611a57608087016060880161591d565b63ffffffff161115611a9d57611a73608086016060870161591d565b600c54604051637aebf00f60e11b8152610b20929162010000900463ffffffff1690600401615938565b6101f4611ab060a087016080880161591d565b63ffffffff161115611aea57611acc60a086016080870161591d565b6101f46040516311ce1afb60e21b8152600401610b20929190615938565b806020018051611af9906156ef565b6001600160401b03169052604081018051611b13906156ef565b6001600160401b031690526020810151600090611b3690873590339087906138f2565b90955090506000611b5a611b55611b5060a08a018a61594f565b61397b565b6139fc565b905085611b65613a6d565b86611b7660808b0160608c0161591d565b611b8660a08c0160808d0161591d565b3386604051602001611b9e9796959493929190615995565b60405160208183030381529060405280519060200120600f600088815260200190815260200160002081905550336001600160a01b03168588600001357feb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e89868c6040016020810190611c1191906158e4565b8d6060016020810190611c24919061591d565b8e6080016020810190611c37919061591d565b89604051611c4a969594939291906159ee565b60405180910390a4505060009283526020918252604092839020815181549383015192909401516001600160481b0319909316931515610100600160481b031916939093176101006001600160401b039283160217600160481b600160881b031916600160481b91909216021790555b919050565b6000611cc9612faf565b6007546001600160401b031633611ce1600143615740565b6040516001600160601b0319606093841b81166020830152914060348201523090921b1660548201526001600160c01b031960c083901b16606882015260700160408051601f1981840301815291905280516020909101209150611d46816001615a2d565b600780546001600160401b0319166001600160401b03928316179055604080516000808252608082018352602080830182815283850183815260608086018581528a86526006855287862093518454935191516001600160601b039182166001600160c01b031990951694909417600160601b9190921602176001600160c01b0316600160c01b9290981691909102969096179055835194850184523385528481018281528585018481528884526005835294909220855181546001600160a01b03199081166001600160a01b039283161783559351600183018054909516911617909255925180519294939192611e449260028501920190614df9565b50611e5491506008905084613aee565b50827f1d3015d7ba850fa198dc7b1a3f5d42779313a681035f77c8c03764c61005518d33604051611e859190614f9a565b60405180910390a2505090565b611e9a612faf565b6002546001600160a01b03163314611ec5576040516344b0e3c360e01b815260040160405180910390fd5b60208114611ee657604051638129bbcd60e01b815260040160405180910390fd5b6000611ef4828401846152eb565b6000818152600560205260409020549091506001600160a01b0316611f2c57604051630fb532db60e11b815260040160405180910390fd5b600081815260066020526040812080546001600160601b031691869190611f53838561589a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555084600a60008282829054906101000a90046001600160601b0316611f9b919061589a565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550817f1ced9348ff549fceab2ac57cd3a9de38edaaab274b725ee82c23e8fc8c4eec7a828784611fee91906158ba565b604051611ffc9291906156b2565b60405180910390a2505050505050565b612014613181565b60c861ffff8a16111561204157888960c860405163539c34bb60e11b8152600401610b20939291906158ff565b60008513612065576040516321ea67b360e11b815260048101869052602401610b20565b8363ffffffff168363ffffffff1611156120965782846040516313c06e5960e11b8152600401610b20929190615938565b609b60ff831611156120c05781609b604051631d66288d60e11b8152600401610b20929190615a4d565b609b60ff821611156120ea5780609b604051631d66288d60e11b8152600401610b20929190615a4d565b604080516101208101825261ffff8b1680825263ffffffff808c16602084018190526000848601528b8216606085018190528b8316608086018190528a841660a08701819052938a1660c0870181905260ff808b1660e08901819052908a16610100909801889052600c8054600160c01b90990260ff60c01b19600160b81b9093029290921661ffff60b81b19600160981b90940263ffffffff60981b19600160781b90990298909816600160781b600160b81b0319600160581b90960263ffffffff60581b19600160381b90980297909716600160301b600160781b03196201000090990265ffffffffffff19909c16909a179a909a1796909616979097179390931791909116959095179290921793909316929092179190911790556010869055517f2c6b6b12413678366b05b145c5f00745bdd00e739131ab5de82484a50c9d78b69061229b908b908b908b908b908b908b908b908b908b9061ffff99909916895263ffffffff97881660208a0152958716604089015293861660608801526080870192909252841660a086015290921660c084015260ff91821660e0840152166101008201526101200190565b60405180910390a1505050505050505050565b6122b6613181565b6000818152600560205260409020546001600160a01b0316806122ec57604051630fb532db60e11b815260040160405180910390fd5b6113d78282612fdc565b606060006123046008613afa565b905080841061232657604051631390f2a160e01b815260040160405180910390fd5b600061233284866158ba565b905081811180612340575083155b61234a578061234c565b815b9050600061235a8683615740565b9050806001600160401b0381111561237457612374614fcb565b60405190808252806020026020018201604052801561239d578160200160208202803683370190505b50935060005b818110156123ed576123c06123b888836158ba565b600890613b04565b8582815181106123d2576123d26156c0565b60209081029190910101526123e6816156d6565b90506123a3565b505050505b92915050565b612400612faf565b6000818152600560205260409020546001600160a01b03168061243657604051630fb532db60e11b815260040160405180910390fd5b6000828152600560205260409020600101546001600160a01b0316331461248d576000828152600560205260409081902060010154905163d084e97560e01b8152610b20916001600160a01b031690600401614f9a565b600082815260056020526040908190208054336001600160a01b031991821681178355600190920180549091169055905183917fd4114ab6e9af9f597c52041f32d62dc57c5c4e4c0d4427006069635e216c9386916118f9918591615a61565b816124f781612f4e565b6124ff612faf565b6001600160a01b03821660009081526004602090815260408083208684529091529020805460ff16156125325750505050565b6000848152600560205260409020600201805460631901612566576040516305a48e0f60e01b815260040160405180910390fd5b8154600160ff1990911681178355815490810182556000828152602090200180546001600160a01b0319166001600160a01b03861617905560405185907f1e980d04aa7648e205713e5e8ea3808672ac163d10936d36f91b2c88ac1575e1906125d0908790614f9a565b60405180910390a25050505050565b6000816040516020016125f29190615a9e565b604051602081830303815290604052805190602001209050919050565b8161261981612f4e565b612621612faf565b61262a836111a5565b1561264857604051631685ecdd60e31b815260040160405180910390fd5b6001600160a01b038216600090815260046020908152604080832086845290915290205460ff166126905782826040516379bfd40160e01b8152600401610b209291906158cd565b6000838152600560209081526040808320600201805482518185028101850190935280835291929091908301828280156126f357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116126d5575b5050505050905060006001825161270a9190615740565b905060005b825181101561281357846001600160a01b0316838281518110612734576127346156c0565b60200260200101516001600160a01b03160361280357600083838151811061275e5761275e6156c0565b6020026020010151905080600560008981526020019081526020016000206002018381548110612790576127906156c0565b600091825260208083209190910180546001600160a01b0319166001600160a01b0394909416939093179092558881526005909152604090206002018054806127db576127db615aac565b600082815260209020810160001990810180546001600160a01b031916905501905550612813565b61280c816156d6565b905061270f565b506001600160a01b038416600090815260046020908152604080832088845290915290819020805460ff191690555185907f32158c6058347c1601b2d12bc696ac6901d8a9a9aa3ba10c27ab0a983e8425a7906125d0908790614f9a565b600061287f82840184615ad9565b9050806000015160ff166001146128af57805160405163237d181f60e21b8152610b209190600190600401615a4d565b8060a001516001600160601b031634146128f35760a08101516040516306acf13560e41b81523460048201526001600160601b039091166024820152604401610b20565b6020808201516000908152600590915260409020546001600160a01b03161561292f576040516326afa43560e11b815260040160405180910390fd5b60005b816060015151811015612a2857604051806060016040528060011515815260200160006001600160401b0316815260200160006001600160401b0316815250600460008460600151848151811061298b5761298b6156c0565b6020908102919091018101516001600160a01b0316825281810192909252604090810160009081208684015182528352819020835181549385015194909201516001600160481b0319909316911515610100600160481b031916919091176101006001600160401b039485160217600160481b600160881b031916600160481b939092169290920217905580612a20816156d6565b915050612932565b50604080516060808201835260808401516001600160601b03908116835260a0850151811660208085019182526000858701818152828901805183526006845288832097518854955192516001600160401b0316600160c01b026001600160c01b03938816600160601b026001600160c01b0319909716919097161794909417169390931790945584518084018652868601516001600160a01b03908116825281860184815294880151828801908152925184526005865295909220825181549087166001600160a01b0319918216178255935160018201805491909716941693909317909455925180519192612b2792600285019290910190614df9565b5050506080810151600a8054600090612b4a9084906001600160601b031661589a565b92506101000a8154816001600160601b0302191690836001600160601b031602179055508060a00151600a600c8282829054906101000a90046001600160601b0316612b96919061589a565b92506101000a8154816001600160601b0302191690836001600160601b03160217905550612bd281602001516008613aee90919063ffffffff16565b50505050565b600e8181548110612be857600080fd5b600091825260209091200154905081565b81612c0381612f4e565b612c0b612faf565b600083815260056020526040902060018101546001600160a01b03848116911614612bd2576001810180546001600160a01b0319166001600160a01b03851617905560405184907f21a4dad170a6bf476c31bbcf4a16628295b0e450672eec25d7c93308e05344a190612c819033908790615a61565b60405180910390a250505050565b600081815260056020526040812054819081906001600160a01b0316606081612ccb57604051630fb532db60e11b815260040160405180910390fd5b600086815260066020908152604080832054600583529281902060020180548251818502810185019093528083526001600160601b0380861695600160601b810490911694600160c01b9091046001600160401b0316938893929091839190830182828015612d6357602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311612d45575b505050505090509450945094509450945091939590929450565b612d85613181565b6002546001600160a01b0316612dae5760405163c1f0c0a160e01b815260040160405180910390fd5b6002546040516370a0823160e01b81526000916001600160a01b0316906370a0823190612ddf903090600401614f9a565b602060405180830381865afa158015612dfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e209190615c04565b600a549091506001600160601b031681811115612e545780826040516354ced18160e11b8152600401610b209291906156b2565b81811015610994576000612e688284615740565b60025460405163a9059cbb60e01b81529192506001600160a01b03169063a9059cbb90612e9b908790859060040161586a565b6020604051808303816000875af1158015612eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ede919061584d565b612efb57604051631f01ff1360e21b815260040160405180910390fd5b7f59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b4366008482604051612f2c92919061586a565b60405180910390a150505050565b612f42613181565b612f4b81613b10565b50565b6000818152600560205260409020546001600160a01b031680612f8457604051630fb532db60e11b815260040160405180910390fd5b336001600160a01b038216146113d75780604051636c51fda960e11b8152600401610b209190614f9a565b600c54600160301b900460ff1615612fda5760405163769dd35360e11b815260040160405180910390fd5b565b600080612fe88461374a565b60025491935091506001600160a01b03161580159061300f57506001600160601b03821615155b156130af5760025460405163a9059cbb60e01b81526001600160a01b039091169063a9059cbb9061304f9086906001600160601b0387169060040161586a565b6020604051808303816000875af115801561306e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613092919061584d565b6130af57604051631e9acf1760e31b815260040160405180910390fd5b6000836001600160a01b0316826001600160601b031660405160006040518083038185875af1925050503d8060008114613105576040519150601f19603f3d011682016040523d82523d6000602084013e61310a565b606091505b505090508061312c5760405163950b247960e01b815260040160405180910390fd5b604080516001600160a01b03861681526001600160601b03808616602083015284169181019190915285907f8c74ce8b8cf87f5eb001275c8be27eb34ea2b62bfab6814fcc62192bb63e81c4906060016125d0565b6000546001600160a01b03163314612fda5760405162461bcd60e51b815260206004820152601660248201527527b7363c9031b0b63630b1363290313c9037bbb732b960511b6044820152606401610b20565b6040805160a0810182526000606082018181526080830182905282526020820181905291810191909152600061320d84600001516125df565b6000818152600d602090815260409182902082518084019093525460ff811615158084526101009091046001600160401b0316918301919091529192509061326b57604051631dfd6e1360e21b815260048101839052602401610b20565b60008286608001516040516020016132849291906156b2565b60408051601f1981840301815291815281516020928301206000818152600f90935290822054909250908190036132ce57604051631b44092560e11b815260040160405180910390fd5b85516020808801516040808a015160608b015160808c015160a08d015193516132fd978a979096959101615c1d565b6040516020818303038152906040528051906020012081146133325760405163354a450b60e21b815260040160405180910390fd5b60006133418760000151613bb3565b9050806133f9578651604051631d2827a760e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163e9413d389161339591906004016153a6565b602060405180830381865afa1580156133b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133d69190615c04565b9050806133f957865160405163175dadad60e01b8152610b2091906004016153a6565b600088608001518260405160200161341b929190918252602082015260400190565b6040516020818303038152906040528051906020012060001c905060006134428a83613c81565b604080516060810182529788526020880196909652948601949094525092979650505050505050565b6000816001600160401b03163a11156134b157821561349457506001600160401b0381166123f2565b3a8260405163435e532d60e11b8152600401610b20929190615883565b503a92915050565b6000806000631fe543e360e01b86856040516024016134d9929190615c71565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252600c805460ff60301b1916600160301b17905590860151608087015191925061353d9163ffffffff9091169083613cec565b600c805460ff60301b191690559695505050505050565b600080831561357357613568868685613d38565b600091509150613583565b61357e868685613e49565b915091505b94509492505050565b6000818152600660205260409020821561364b5780546001600160601b03600160601b90910481169085168110156135d757604051631e9acf1760e31b815260040160405180910390fd5b6135e18582615692565b8254600160601b600160c01b031916600160601b6001600160601b039283168102919091178455600b805488939192600c9261362192869290041661589a565b92506101000a8154816001600160601b0302191690836001600160601b0316021790555050612bd2565b80546001600160601b0390811690851681101561367b57604051631e9acf1760e31b815260040160405180910390fd5b6136858582615692565b82546001600160601b0319166001600160601b03918216178355600b805487926000916136b49185911661589a565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505050505050565b601154600090815b8181101561374057836001600160a01b03166011828154811061370c5761370c6156c0565b6000918252602090912001546001600160a01b031603613730575060019392505050565b613739816156d6565b90506136e7565b5060009392505050565b60008181526005602090815260408083206006909252822054600290910180546001600160601b0380841694600160601b90940416925b818110156137ec576004600084838154811061379f5761379f6156c0565b60009182526020808320909101546001600160a01b031683528281019390935260409182018120898252909252902080546001600160881b03191690556137e5816156d6565b9050613781565b50600085815260056020526040812080546001600160a01b031990811682556001820180549091169055906138246002830182614e5e565b505060008581526006602052604081205561384060088661403a565b506001600160601b0384161561389357600a805485919060009061386e9084906001600160601b0316615692565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b6001600160601b038316156138eb5782600a600c8282829054906101000a90046001600160601b03166138c69190615692565b92506101000a8154816001600160601b0302191690836001600160601b031602179055505b5050915091565b60408051602081018690526001600160a01b03851691810191909152606081018390526001600160401b03821660808201526000908190819060a00160408051601f1981840301815290829052805160209182012092506139579189918491016156b2565b60408051808303601f19018152919052805160209091012097909650945050505050565b60408051602081019091526000815260008290036139a857506040805160208101909152600081526123f2565b63125fa26760e31b6139ba8385615c92565b6001600160e01b031916146139e257604051632923fee760e11b815260040160405180910390fd5b6139ef8260048186615cc2565b810190610dfb9190615cec565b60607f92fd13387c7fe7befbc38d303d6468778fb9731bc4583f17d92989c6fcfdeaaa82604051602401613a3591511515815260200190565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915292915050565b600046613a7981614046565b15613ae75760646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ae19190615c04565b91505090565b4391505090565b6000610dfb8383614069565b60006123f2825490565b6000610dfb83836140b8565b336001600160a01b03821603613b625760405162461bcd60e51b815260206004820152601760248201527621b0b73737ba103a3930b739b332b9103a379039b2b63360491b6044820152606401610b20565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600046613bbf81614046565b15613c7257610100836001600160401b0316613bd9613a6d565b613be39190615740565b1180613bff5750613bf2613a6d565b836001600160401b031610155b15613c0d5750600092915050565b6040516315a03d4160e11b8152606490632b407a8290613c319086906004016153a6565b602060405180830381865afa158015613c4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfb9190615c04565b50506001600160401b03164090565b6000613cb58360000151846020015185604001518660600151868860a001518960c001518a60e001518b61010001516140e2565b60038360200151604051602001613ccd929190615d37565b60408051601f1981840301815291905280516020909101209392505050565b60005a611388811015613cfe57600080fd5b611388810390508460408204820311613d1657600080fd5b50823b613d2257600080fd5b60008083516020850160008789f1949350505050565b600080613d7b6000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506142fd92505050565b905060005a600c54613d9b908890600160581b900463ffffffff166158ba565b613da59190615740565b613daf9086615d4b565b600c54909150600090613dd490600160781b900463ffffffff1664e8d4a51000615d4b565b90508415613e2057600c548190606490600160b81b900460ff16613df885876158ba565b613e029190615d4b565b613e0c9190615d78565b613e1691906158ba565b9350505050610dfb565b600c548190606490613e3c90600160b81b900460ff1682615d8c565b60ff16613df885876158ba565b600080600080613e576143d0565b9150915060008213613e7f576040516321ea67b360e11b815260048101839052602401610b20565b6000613ec16000368080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506142fd92505050565b9050600083825a600c54613ee3908d90600160581b900463ffffffff166158ba565b613eed9190615740565b613ef7908b615d4b565b613f0191906158ba565b613f1390670de0b6b3a7640000615d4b565b613f1d9190615d78565b600c54909150600090613f469063ffffffff600160981b8204811691600160781b900416615da5565b613f5b9063ffffffff1664e8d4a51000615d4b565b9050600085613f7283670de0b6b3a7640000615d4b565b613f7c9190615d78565b905060008915613fbd57600c548290606490613fa290600160c01b900460ff1687615d4b565b613fac9190615d78565b613fb691906158ba565b9050613ffd565b600c548290606490613fd990600160c01b900460ff1682615d8c565b613fe69060ff1687615d4b565b613ff09190615d78565b613ffa91906158ba565b90505b676765c793fa10079d601b1b8111156140295760405163e80fa38160e01b815260040160405180910390fd5b9b949a509398505050505050505050565b6000610dfb8383614497565b600061a4b182148061405a575062066eed82145b806123f257505062066eee1490565b60008181526001830160205260408120546140b0575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556123f2565b5060006123f2565b60008260000182815481106140cf576140cf6156c0565b9060005260206000200154905092915050565b6140eb89614591565b6141345760405162461bcd60e51b815260206004820152601a6024820152797075626c6963206b6579206973206e6f74206f6e20637572766560301b6044820152606401610b20565b61413d88614591565b6141815760405162461bcd60e51b815260206004820152601560248201527467616d6d61206973206e6f74206f6e20637572766560581b6044820152606401610b20565b61418a83614591565b6141d65760405162461bcd60e51b815260206004820152601d60248201527f6347616d6d615769746e657373206973206e6f74206f6e2063757276650000006044820152606401610b20565b6141df82614591565b61422a5760405162461bcd60e51b815260206004820152601c60248201527b73486173685769746e657373206973206e6f74206f6e20637572766560201b6044820152606401610b20565b614236878a8887614654565b61427e5760405162461bcd60e51b81526020600482015260196024820152786164647228632a706b2b732a6729213d5f755769746e65737360381b6044820152606401610b20565b600061428a8a87614768565b9050600061429d898b878b8689896147cc565b905060006142ae838d8d8a866148eb565b9050808a146142ef5760405162461bcd60e51b815260206004820152600d60248201526c34b73b30b634b210383937b7b360991b6044820152606401610b20565b505050505050505050505050565b60004661430981614046565b1561434d57606c6001600160a01b031663c6f7de0e6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613c4e573d6000803e3d6000fd5b6143568161492b565b156143c757600f602160991b016001600160a01b03166349948e0e84604051806080016040528060488152602001615f186048913960405160200161439c929190615dc2565b6040516020818303038152906040526040518263ffffffff1660e01b8152600401613c319190615818565b50600092915050565b600c5460035460408051633fabe5a360e21b815290516000938493600160381b90910463ffffffff169284926001600160a01b039092169163feaf968c9160048082019260a0929091908290030181865afa158015614433573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144579190615e08565b50919650909250505063ffffffff821615801590614483575061447a8142615740565b8263ffffffff16105b925082156144915760105493505b50509091565b600081815260018301602052604081205480156145805760006144bb600183615740565b85549091506000906144cf90600190615740565b90508181146145345760008660000182815481106144ef576144ef6156c0565b9060005260206000200154905080876000018481548110614512576145126156c0565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061454557614545615aac565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506123f2565b60009150506123f2565b5092915050565b80516000906401000003d019116145df5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420782d6f7264696e61746560701b6044820152606401610b20565b60208201516401000003d0191161462d5760405162461bcd60e51b8152602060048201526012602482015271696e76616c696420792d6f7264696e61746560701b6044820152606401610b20565b60208201516401000003d01990800961464d8360005b6020020151614965565b1492915050565b60006001600160a01b03821661469a5760405162461bcd60e51b815260206004820152600b60248201526a626164207769746e65737360a81b6044820152606401610b20565b6020840151600090600116156146b157601c6146b4565b601b5b9050600070014551231950b75fc4402da1732fc9bebe1985876000602002015109865170014551231950b75fc4402da1732fc9bebe199182039250600091908909875160408051600080825260209091019182905292935060019161471e91869188918790615e58565b6020604051602081039080840390855afa158015614740573d6000803e3d6000fd5b5050604051601f1901516001600160a01b039081169088161495505050505050949350505050565b614770614e7c565b61479d6001848460405160200161478993929190615e76565b604051602081830303815290604052614989565b90505b6147a981614591565b6123f25780516040805160208101929092526147c59101614789565b90506147a0565b6147d4614e7c565b825186516401000003d01991829006919006036148335760405162461bcd60e51b815260206004820152601e60248201527f706f696e747320696e2073756d206d7573742062652064697374696e637400006044820152606401610b20565b61483e8789886149d6565b6148835760405162461bcd60e51b8152602060048201526016602482015275119a5c9cdd081b5d5b0818da1958dac819985a5b195960521b6044820152606401610b20565b61488e8486856149d6565b6148d45760405162461bcd60e51b815260206004820152601760248201527614d958dbdb99081b5d5b0818da1958dac819985a5b1959604a1b6044820152606401610b20565b6148df868484614af4565b98975050505050505050565b60006002868686858760405160200161490996959493929190615e97565b60408051601f1981840301815291905280516020909101209695505050505050565b6000600a82148061493d57506101a482145b8061494a575062aa37dc82145b80614956575061210582145b806123f257505062014a331490565b6000806401000003d01980848509840990506401000003d019600782089392505050565b614991614e7c565b61499a82614bb7565b81526149af6149aa826000614643565b614bf2565b6020820181905260029006600103611cba576020810180516401000003d019039052919050565b600082600003614a165760405162461bcd60e51b815260206004820152600b60248201526a3d32b9379039b1b0b630b960a91b6044820152606401610b20565b83516020850151600090614a2c90600290615ef1565b15614a3857601c614a3b565b601b5b9050600070014551231950b75fc4402da1732fc9bebe19838709604080516000808252602090910191829052919250600190614a7e908390869088908790615e58565b6020604051602081039080840390855afa158015614aa0573d6000803e3d6000fd5b505050602060405103519050600086604051602001614abf9190615f05565b60408051601f1981840301815291905280516020909101206001600160a01b0392831692169190911498975050505050505050565b614afc614e7c565b835160208086015185519186015160009384938493614b1d93909190614c12565b919450925090506401000003d019858209600114614b795760405162461bcd60e51b815260206004820152601960248201527834b73b2d1036bab9ba1031329034b73b32b939b29037b3103d60391b6044820152606401610b20565b60405180604001604052806401000003d01980614b9857614b98615d62565b87860981526020016401000003d0198785099052979650505050505050565b805160208201205b6401000003d0198110611cba57604080516020808201939093528151808203840181529082019091528051910120614bbf565b60006123f2826002614c0b6401000003d01960016158ba565b901c614cf2565b60008080600180826401000003d019896401000003d019038808905060006401000003d0198b6401000003d019038a0890506000614c5283838585614d8c565b9098509050614c6388828e88614db0565b9098509050614c7488828c87614db0565b90985090506000614c878d878b85614db0565b9098509050614c9888828686614d8c565b9098509050614ca988828e89614db0565b9098509050818114614cde576401000003d019818a0998506401000003d01982890997506401000003d0198183099650614ce2565b8196505b5050505050509450945094915050565b600080614cfd614e9a565b6020808252818101819052604082015260608101859052608081018490526401000003d01960a0820152614d2f614eb8565b60208160c0846005600019fa925082600003614d825760405162461bcd60e51b81526020600482015260126024820152716269674d6f64457870206661696c7572652160701b6044820152606401610b20565b5195945050505050565b6000806401000003d0198487096401000003d0198487099097909650945050505050565b600080806401000003d019878509905060006401000003d01987876401000003d019030990506401000003d0198183086401000003d01986890990999098509650505050505050565b828054828255906000526020600020908101928215614e4e579160200282015b82811115614e4e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614e19565b50614e5a929150614ed6565b5090565b5080546000825590600052602060002090810190612f4b9190614ed6565b60405180604001604052806002906020820280368337509192915050565b6040518060c001604052806006906020820280368337509192915050565b60405180602001604052806001906020820280368337509192915050565b5b80821115614e5a5760008155600101614ed7565b60006060820161ffff86168352602063ffffffff86168185015260606040850152818551808452608086019150828701935060005b81811015614f3c57845183529383019391830191600101614f20565b509098975050505050505050565b6001600160a01b0381168114612f4b57600080fd5b8035611cba81614f4a565b60008060408385031215614f7d57600080fd5b823591506020830135614f8f81614f4a565b809150509250929050565b6001600160a01b0391909116815260200190565b600060208284031215614fc057600080fd5b8135610dfb81614f4a565b634e487b7160e01b600052604160045260246000fd5b60405160c081016001600160401b038111828210171561500357615003614fcb565b60405290565b60405161012081016001600160401b038111828210171561500357615003614fcb565b604051601f8201601f191681016001600160401b038111828210171561505457615054614fcb565b604052919050565b600082601f83011261506d57600080fd5b604080519081016001600160401b038111828210171561508f5761508f614fcb565b80604052508060408401858111156150a657600080fd5b845b818110156150c05780358352602092830192016150a8565b509195945050505050565b80356001600160401b0381168114611cba57600080fd5b803563ffffffff81168114611cba57600080fd5b600060c0828403121561510857600080fd5b615110614fe1565b905061511b826150cb565b815260208083013581830152615133604084016150e2565b6040830152615144606084016150e2565b6060830152608083013561515781614f4a565b608083015260a08301356001600160401b038082111561517657600080fd5b818501915085601f83011261518a57600080fd5b81358181111561519c5761519c614fcb565b6151ae601f8201601f1916850161502c565b915080825286848285010111156151c457600080fd5b80848401858401376000848284010152508060a085015250505092915050565b8015158114612f4b57600080fd5b8035611cba816151e4565b60008060008385036101e081121561521457600080fd5b6101a08082121561522457600080fd5b61522c615009565b9150615238878761505c565b8252615247876040880161505c565b60208301526080860135604083015260a0860135606083015260c0860135608083015261527660e08701614f5f565b60a083015261010061528a8882890161505c565b60c084015261529d88610140890161505c565b60e0840152610180870135908301529093508401356001600160401b038111156152c657600080fd5b6152d2868287016150f6565b9250506152e26101c085016151f2565b90509250925092565b6000602082840312156152fd57600080fd5b5035919050565b6000806040838503121561531757600080fd5b823561532281614f4a565b91506020830135614f8f81614f4a565b6000806060838503121561534557600080fd5b604083018481111561535657600080fd5b839250615362816150cb565b9150509250929050565b60006020828403121561537e57600080fd5b81356001600160401b0381111561539457600080fd5b820160c08185031215610dfb57600080fd5b6001600160401b0391909116815260200190565b60008083601f8401126153cc57600080fd5b5081356001600160401b038111156153e357600080fd5b6020830191508360208285010111156153fb57600080fd5b9250929050565b6000806000806060858703121561541857600080fd5b843561542381614f4a565b93506020850135925060408501356001600160401b0381111561544557600080fd5b615451878288016153ba565b95989497509550505050565b803561ffff81168114611cba57600080fd5b803560ff81168114611cba57600080fd5b60008060008060008060008060006101208a8c03121561549f57600080fd5b6154a88a61545d565b98506154b660208b016150e2565b97506154c460408b016150e2565b96506154d260608b016150e2565b955060808a013594506154e760a08b016150e2565b93506154f560c08b016150e2565b925061550360e08b0161546f565b91506155126101008b0161546f565b90509295985092959850929598565b6000806040838503121561553457600080fd5b50508035926020909101359150565b600081518084526020808501945080840160005b8381101561557357815187529582019590820190600101615557565b509495945050505050565b602081526000610dfb6020830184615543565b6000604082840312156155a357600080fd5b610dfb838361505c565b600080602083850312156155c057600080fd5b82356001600160401b038111156155d657600080fd5b6155e2858286016153ba565b90969095509350505050565b600081518084526020808501945080840160005b838110156155735781516001600160a01b031687529582019590820190600101615602565b6001600160601b038681168252851660208201526001600160401b03841660408201526001600160a01b038316606082015260a060808201819052600090615671908301846155ee565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6001600160601b0382811682821603908082111561458a5761458a61567c565b918252602082015260400190565b634e487b7160e01b600052603260045260246000fd5b6000600182016156e8576156e861567c565b5060010190565b60006001600160401b038281166002600160401b031981016157135761571361567c565b6001019392505050565b60006001600160401b038216806157365761573661567c565b6000190192915050565b818103818111156123f2576123f261567c565b6020815260ff82511660208201526020820151604082015260018060a01b0360408301511660608201526000606083015160c0608084015261579860e08401826155ee565b60808501516001600160601b0390811660a0868101919091529095015190941660c0909301929092525090919050565b60005b838110156157e35781810151838201526020016157cb565b50506000910152565b600081518084526158048160208601602086016157c8565b601f01601f19169290920160200192915050565b602081526000610dfb60208301846157ec565b6001600160a01b039290921682526001600160601b0316602082015260400190565b60006020828403121561585f57600080fd5b8151610dfb816151e4565b6001600160a01b03929092168252602082015260400190565b9182526001600160401b0316602082015260400190565b6001600160601b0381811683821601908082111561458a5761458a61567c565b808201808211156123f2576123f261567c565b9182526001600160a01b0316602082015260400190565b6000602082840312156158f657600080fd5b610dfb8261545d565b61ffff93841681529183166020830152909116604082015260600190565b60006020828403121561592f57600080fd5b610dfb826150e2565b63ffffffff92831681529116602082015260400190565b6000808335601e1984360301811261596657600080fd5b8301803591506001600160401b0382111561598057600080fd5b6020019150368190038213156153fb57600080fd5b878152602081018790526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c082018190526000906159e1908301846157ec565b9998505050505050505050565b86815285602082015261ffff85166040820152600063ffffffff808616606084015280851660808401525060c060a08301526148df60c08301846157ec565b6001600160401b0381811683821601908082111561458a5761458a61567c565b60ff92831681529116602082015260400190565b6001600160a01b0392831681529116602082015260400190565b8060005b6002811015612bd2578151845260209384019390910190600101615a7f565b604081016123f28284615a7b565b634e487b7160e01b600052603160045260246000fd5b80356001600160601b0381168114611cba57600080fd5b60006020808385031215615aec57600080fd5b82356001600160401b0380821115615b0357600080fd5b9084019060c08287031215615b1757600080fd5b615b1f614fe1565b615b288361546f565b815283830135848201526040830135615b4081614f4a565b6040820152606083013582811115615b5757600080fd5b8301601f81018813615b6857600080fd5b803583811115615b7a57615b7a614fcb565b8060051b9350615b8b86850161502c565b818152938201860193868101908a861115615ba557600080fd5b928701925b85841015615bcf5783359250615bbf83614f4a565b8282529287019290870190615baa565b606085015250615be491505060808401615ac2565b6080820152615bf560a08401615ac2565b60a08201529695505050505050565b600060208284031215615c1657600080fd5b5051919050565b8781526001600160401b03871660208201526040810186905263ffffffff8581166060830152841660808201526001600160a01b03831660a082015260e060c082018190526000906159e1908301846157ec565b828152604060208201526000615c8a6040830184615543565b949350505050565b6001600160e01b03198135818116916004851015615cba5780818660040360031b1b83161692505b505092915050565b60008085851115615cd257600080fd5b83861115615cdf57600080fd5b5050820193919092039150565b600060208284031215615cfe57600080fd5b604051602081016001600160401b0381118282101715615d2057615d20614fcb565b6040528235615d2e816151e4565b81529392505050565b82815260608101610dfb6020830184615a7b565b80820281158282048414176123f2576123f261567c565b634e487b7160e01b600052601260045260246000fd5b600082615d8757615d87615d62565b500490565b60ff81811683821601908111156123f2576123f261567c565b63ffffffff82811682821603908082111561458a5761458a61567c565b60008351615dd48184602088016157c8565b835190830190615de88183602088016157c8565b01949350505050565b80516001600160501b0381168114611cba57600080fd5b600080600080600060a08688031215615e2057600080fd5b615e2986615df1565b9450602086015193506040860151925060608601519150615e4c60808701615df1565b90509295509295909350565b93845260ff9290921660208401526040830152606082015260800190565b838152615e866020820184615a7b565b606081019190915260800192915050565b868152615ea76020820187615a7b565b615eb46060820186615a7b565b615ec160a0820185615a7b565b615ece60e0820184615a7b565b60609190911b6001600160601b0319166101208201526101340195945050505050565b600082615f0057615f00615d62565b500690565b615f0f8183615a7b565b60400191905056fe307866666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666a164736f6c6343000813000a", } var VRFCoordinatorV2PlusUpgradedVersionABI = VRFCoordinatorV2PlusUpgradedVersionMetaData.ABI @@ -559,6 +559,28 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionC return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SCurrentSubNonce(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts) } +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCaller) SFallbackWeiPerUnitLink(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _VRFCoordinatorV2PlusUpgradedVersion.contract.Call(opts, &out, "s_fallbackWeiPerUnitLink") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) SFallbackWeiPerUnitLink() (*big.Int, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SFallbackWeiPerUnitLink(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCallerSession) SFallbackWeiPerUnitLink() (*big.Int, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SFallbackWeiPerUnitLink(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts) +} + func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCaller) SProvingKeyHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { var out []interface{} err := _VRFCoordinatorV2PlusUpgradedVersion.contract.Call(opts, &out, "s_provingKeyHashes", arg0) @@ -581,6 +603,36 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionC return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SProvingKeyHashes(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts, arg0) } +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCaller) SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (SProvingKeys, + + error) { + var out []interface{} + err := _VRFCoordinatorV2PlusUpgradedVersion.contract.Call(opts, &out, "s_provingKeys", arg0) + + outstruct := new(SProvingKeys) + if err != nil { + return *outstruct, err + } + + outstruct.Exists = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.MaxGas = *abi.ConvertType(out[1], new(uint64)).(*uint64) + + return *outstruct, err + +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) SProvingKeys(arg0 [32]byte) (SProvingKeys, + + error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SProvingKeys(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts, arg0) +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCallerSession) SProvingKeys(arg0 [32]byte) (SProvingKeys, + + error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.SProvingKeys(&_VRFCoordinatorV2PlusUpgradedVersion.CallOpts, arg0) +} + func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionCaller) SRequestCommitments(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) { var out []interface{} err := _VRFCoordinatorV2PlusUpgradedVersion.contract.Call(opts, &out, "s_requestCommitments", arg0) @@ -707,16 +759,16 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionT return _VRFCoordinatorV2PlusUpgradedVersion.Contract.CreateSubscription(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) FulfillRandomWords(opts *bind.TransactOpts, proof VRFProof, rc VRFCoordinatorV2PlusUpgradedVersionRequestCommitment, arg2 bool) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "fulfillRandomWords", proof, rc, arg2) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) FulfillRandomWords(opts *bind.TransactOpts, proof VRFProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "fulfillRandomWords", proof, rc, onlyPremium) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) FulfillRandomWords(proof VRFProof, rc VRFCoordinatorV2PlusUpgradedVersionRequestCommitment, arg2 bool) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.FulfillRandomWords(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, proof, rc, arg2) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) FulfillRandomWords(proof VRFProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.FulfillRandomWords(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, proof, rc, onlyPremium) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) FulfillRandomWords(proof VRFProof, rc VRFCoordinatorV2PlusUpgradedVersionRequestCommitment, arg2 bool) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.FulfillRandomWords(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, proof, rc, arg2) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) FulfillRandomWords(proof VRFProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.FulfillRandomWords(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, proof, rc, onlyPremium) } func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) FundSubscriptionWithNative(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) { @@ -815,16 +867,16 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionT return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterMigratableCoordinator(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, target) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "registerProvingKey", publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.contract.Transact(opts, "registerProvingKey", publicProvingKey, maxGas) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionSession) RegisterProvingKey(publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey, maxGas) } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) RegisterProvingKey(publicProvingKey [2]*big.Int) (*types.Transaction, error) { - return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey) +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactorSession) RegisterProvingKey(publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) { + return _VRFCoordinatorV2PlusUpgradedVersion.Contract.RegisterProvingKey(&_VRFCoordinatorV2PlusUpgradedVersion.TransactOpts, publicProvingKey, maxGas) } func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionTransactor) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) { @@ -984,14 +1036,16 @@ func (it *VRFCoordinatorV2PlusUpgradedVersionConfigSetIterator) Close() error { } type VRFCoordinatorV2PlusUpgradedVersionConfigSet struct { - MinimumRequestConfirmations uint16 - MaxGasLimit uint32 - StalenessSeconds uint32 - GasAfterPaymentCalculation uint32 - FallbackWeiPerUnitLink *big.Int - NativePremiumPercentage uint8 - LinkPremiumPercentage uint8 - Raw types.Log + MinimumRequestConfirmations uint16 + MaxGasLimit uint32 + StalenessSeconds uint32 + GasAfterPaymentCalculation uint32 + FallbackWeiPerUnitLink *big.Int + FulfillmentFlatFeeNativePPM uint32 + FulfillmentFlatFeeLinkDiscountPPM uint32 + NativePremiumPercentage uint8 + LinkPremiumPercentage uint8 + Raw types.Log } func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterConfigSet(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionConfigSetIterator, error) { @@ -1163,6 +1217,124 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionF return event, nil } +type VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator struct { + Event *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator) Error() error { + return it.fail +} + +func (it *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed struct { + RequestId *big.Int + FallbackWeiPerUnitLink *big.Int + Raw types.Log +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterFallbackWeiPerUnitLinkUsed(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator, error) { + + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.FilterLogs(opts, "FallbackWeiPerUnitLinkUsed") + if err != nil { + return nil, err + } + return &VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator{contract: _VRFCoordinatorV2PlusUpgradedVersion.contract, event: "FallbackWeiPerUnitLinkUsed", logs: logs, sub: sub}, nil +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) WatchFallbackWeiPerUnitLinkUsed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) (event.Subscription, error) { + + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.WatchLogs(opts, "FallbackWeiPerUnitLinkUsed") + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) + if err := _VRFCoordinatorV2PlusUpgradedVersion.contract.UnpackLog(event, "FallbackWeiPerUnitLinkUsed", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) ParseFallbackWeiPerUnitLinkUsed(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed, error) { + event := new(VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) + if err := _VRFCoordinatorV2PlusUpgradedVersion.contract.UnpackLog(event, "FallbackWeiPerUnitLinkUsed", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + type VRFCoordinatorV2PlusUpgradedVersionFundsRecoveredIterator struct { Event *VRFCoordinatorV2PlusUpgradedVersionFundsRecovered @@ -1851,6 +2023,7 @@ func (it *VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegisteredIterator) Close type VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered struct { KeyHash [32]byte + MaxGas uint64 Raw types.Log } @@ -1967,46 +2140,48 @@ func (it *VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator) Close } type VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled struct { - RequestId *big.Int - OutputSeed *big.Int - SubID *big.Int - Payment *big.Int - Success bool - Raw types.Log + RequestId *big.Int + OutputSeed *big.Int + SubId *big.Int + Payment *big.Int + NativePayment bool + Success bool + OnlyPremium bool + Raw types.Log } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subID []*big.Int) (*VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator, error) { +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subId []*big.Int) (*VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator, error) { var requestIdRule []interface{} for _, requestIdItem := range requestId { requestIdRule = append(requestIdRule, requestIdItem) } - var subIDRule []interface{} - for _, subIDItem := range subID { - subIDRule = append(subIDRule, subIDItem) + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) } - logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.FilterLogs(opts, "RandomWordsFulfilled", requestIdRule, subIDRule) + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.FilterLogs(opts, "RandomWordsFulfilled", requestIdRule, subIdRule) if err != nil { return nil, err } return &VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator{contract: _VRFCoordinatorV2PlusUpgradedVersion.contract, event: "RandomWordsFulfilled", logs: logs, sub: sub}, nil } -func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, requestId []*big.Int, subID []*big.Int) (event.Subscription, error) { +func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersionFilterer) WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, requestId []*big.Int, subId []*big.Int) (event.Subscription, error) { var requestIdRule []interface{} for _, requestIdItem := range requestId { requestIdRule = append(requestIdRule, requestIdItem) } - var subIDRule []interface{} - for _, subIDItem := range subID { - subIDRule = append(subIDRule, subIDItem) + var subIdRule []interface{} + for _, subIdItem := range subId { + subIdRule = append(subIdRule, subIdItem) } - logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.WatchLogs(opts, "RandomWordsFulfilled", requestIdRule, subIDRule) + logs, sub, err := _VRFCoordinatorV2PlusUpgradedVersion.contract.WatchLogs(opts, "RandomWordsFulfilled", requestIdRule, subIdRule) if err != nil { return nil, err } @@ -3250,6 +3425,10 @@ type SConfig struct { NativePremiumPercentage uint8 LinkPremiumPercentage uint8 } +type SProvingKeys struct { + Exists bool + MaxGas uint64 +} func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersion) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { @@ -3257,6 +3436,8 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersion) return _VRFCoordinatorV2PlusUpgradedVersion.ParseConfigSet(log) case _VRFCoordinatorV2PlusUpgradedVersion.abi.Events["CoordinatorRegistered"].ID: return _VRFCoordinatorV2PlusUpgradedVersion.ParseCoordinatorRegistered(log) + case _VRFCoordinatorV2PlusUpgradedVersion.abi.Events["FallbackWeiPerUnitLinkUsed"].ID: + return _VRFCoordinatorV2PlusUpgradedVersion.ParseFallbackWeiPerUnitLinkUsed(log) case _VRFCoordinatorV2PlusUpgradedVersion.abi.Events["FundsRecovered"].ID: return _VRFCoordinatorV2PlusUpgradedVersion.ParseFundsRecovered(log) case _VRFCoordinatorV2PlusUpgradedVersion.abi.Events["MigrationCompleted"].ID: @@ -3296,13 +3477,17 @@ func (_VRFCoordinatorV2PlusUpgradedVersion *VRFCoordinatorV2PlusUpgradedVersion) } func (VRFCoordinatorV2PlusUpgradedVersionConfigSet) Topic() common.Hash { - return common.HexToHash("0x95cb2ddab6d2297c29a4861691de69b3969c464aa4a9c44258b101ff02ff375a") + return common.HexToHash("0x2c6b6b12413678366b05b145c5f00745bdd00e739131ab5de82484a50c9d78b6") } func (VRFCoordinatorV2PlusUpgradedVersionCoordinatorRegistered) Topic() common.Hash { return common.HexToHash("0xb7cabbfc11e66731fc77de0444614282023bcbd41d16781c753a431d0af01625") } +func (VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) Topic() common.Hash { + return common.HexToHash("0x6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a") +} + func (VRFCoordinatorV2PlusUpgradedVersionFundsRecovered) Topic() common.Hash { return common.HexToHash("0x59bfc682b673f8cbf945f1e454df9334834abf7dfe7f92237ca29ecb9b436600") } @@ -3324,11 +3509,11 @@ func (VRFCoordinatorV2PlusUpgradedVersionOwnershipTransferred) Topic() common.Ha } func (VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered) Topic() common.Hash { - return common.HexToHash("0xc9583fd3afa3d7f16eb0b88d0268e7d05c09bafa4b21e092cbd1320e1bc8089d") + return common.HexToHash("0x9b911b2c240bfbef3b6a8f7ed6ee321d1258bb2a3fe6becab52ac1cd3210afd3") } func (VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled) Topic() common.Hash { - return common.HexToHash("0x49580fdfd9497e1ed5c1b1cec0495087ae8e3f1267470ec2fb015db32e3d6aa7") + return common.HexToHash("0xaeb4b4786571e184246d39587f659abf0e26f41f6a3358692250382c0cdb47b7") } func (VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested) Topic() common.Hash { @@ -3406,8 +3591,14 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { SCurrentSubNonce(opts *bind.CallOpts) (uint64, error) + SFallbackWeiPerUnitLink(opts *bind.CallOpts) (*big.Int, error) + SProvingKeyHashes(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) + SProvingKeys(opts *bind.CallOpts, arg0 [32]byte) (SProvingKeys, + + error) + SRequestCommitments(opts *bind.CallOpts, arg0 *big.Int) ([32]byte, error) STotalBalance(opts *bind.CallOpts) (*big.Int, error) @@ -3424,7 +3615,7 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { CreateSubscription(opts *bind.TransactOpts) (*types.Transaction, error) - FulfillRandomWords(opts *bind.TransactOpts, proof VRFProof, rc VRFCoordinatorV2PlusUpgradedVersionRequestCommitment, arg2 bool) (*types.Transaction, error) + FulfillRandomWords(opts *bind.TransactOpts, proof VRFProof, rc VRFTypesRequestCommitmentV2Plus, onlyPremium bool) (*types.Transaction, error) FundSubscriptionWithNative(opts *bind.TransactOpts, subId *big.Int) (*types.Transaction, error) @@ -3442,7 +3633,7 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { RegisterMigratableCoordinator(opts *bind.TransactOpts, target common.Address) (*types.Transaction, error) - RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int) (*types.Transaction, error) + RegisterProvingKey(opts *bind.TransactOpts, publicProvingKey [2]*big.Int, maxGas uint64) (*types.Transaction, error) RemoveConsumer(opts *bind.TransactOpts, subId *big.Int, consumer common.Address) (*types.Transaction, error) @@ -3472,6 +3663,12 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { ParseCoordinatorRegistered(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionCoordinatorRegistered, error) + FilterFallbackWeiPerUnitLinkUsed(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsedIterator, error) + + WatchFallbackWeiPerUnitLinkUsed(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed) (event.Subscription, error) + + ParseFallbackWeiPerUnitLinkUsed(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionFallbackWeiPerUnitLinkUsed, error) + FilterFundsRecovered(opts *bind.FilterOpts) (*VRFCoordinatorV2PlusUpgradedVersionFundsRecoveredIterator, error) WatchFundsRecovered(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionFundsRecovered) (event.Subscription, error) @@ -3508,9 +3705,9 @@ type VRFCoordinatorV2PlusUpgradedVersionInterface interface { ParseProvingKeyRegistered(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionProvingKeyRegistered, error) - FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subID []*big.Int) (*VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator, error) + FilterRandomWordsFulfilled(opts *bind.FilterOpts, requestId []*big.Int, subId []*big.Int) (*VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilledIterator, error) - WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, requestId []*big.Int, subID []*big.Int) (event.Subscription, error) + WatchRandomWordsFulfilled(opts *bind.WatchOpts, sink chan<- *VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, requestId []*big.Int, subId []*big.Int) (event.Subscription, error) ParseRandomWordsFulfilled(log types.Log) (*VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) diff --git a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt index d7a1fa84424..8299cd5ff15 100644 --- a/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -99,7 +99,7 @@ vrf_v2_consumer_wrapper: ../../contracts/solc/v0.8.6/VRFv2Consumer/VRFv2Consumer vrf_v2plus_load_test_with_metrics: ../../contracts/solc/v0.8.19/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.abi ../../contracts/solc/v0.8.19/VRFV2PlusLoadTestWithMetrics/VRFV2PlusLoadTestWithMetrics.bin 593dbcdcc212fc9ec69fe71684711d112433cc31218fe21305ace9229ac29289 vrf_v2plus_single_consumer: ../../contracts/solc/v0.8.19/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusSingleConsumerExample/VRFV2PlusSingleConsumerExample.bin cfdfb97b1b0801ee778410d54b1f6541395ac01ab592ffd6c3feaf4a3ac3eca2 vrf_v2plus_sub_owner: ../../contracts/solc/v0.8.19/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusExternalSubOwnerExample/VRFV2PlusExternalSubOwnerExample.bin 6032a081ad15453e52af1cf37c74a9f77f2a30bc14b2cb35f564eabc4b0b4c2e -vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.19/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.19/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin 4a7df5b066bc3944622009659828fae35bc39d15cf4d218c1560dbdf39b10de2 +vrf_v2plus_upgraded_version: ../../contracts/solc/v0.8.19/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.abi ../../contracts/solc/v0.8.19/VRFCoordinatorV2PlusUpgradedVersion/VRFCoordinatorV2PlusUpgradedVersion.bin 50429c68bc9e4edcddc4b15d65867bff9ae308314b52ed997e7d5665f0703148 vrfv2_proxy_admin: ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.abi ../../contracts/solc/v0.8.6/VRFV2ProxyAdmin/VRFV2ProxyAdmin.bin 402b1103087ffe1aa598854a8f8b38f8cd3de2e3aaa86369e28017a9157f4980 vrfv2_reverting_example: ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.abi ../../contracts/solc/v0.8.6/VRFV2RevertingExample/VRFV2RevertingExample.bin 1ae46f80351d428bd85ba58b9041b2a608a1845300d79a8fed83edf96606de87 vrfv2_transparent_upgradeable_proxy: ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.abi ../../contracts/solc/v0.8.6/VRFV2TransparentUpgradeableProxy/VRFV2TransparentUpgradeableProxy.bin fe1a8e6852fbd06d91f64315c5cede86d340891f5b5cc981fb5b86563f7eac3f diff --git a/integration-tests/actions/vrf/common/logging_helpers.go b/integration-tests/actions/vrf/common/logging_helpers.go new file mode 100644 index 00000000000..f9c8a031678 --- /dev/null +++ b/integration-tests/actions/vrf/common/logging_helpers.go @@ -0,0 +1,129 @@ +package common + +import ( + "fmt" + "math/big" + + "github.com/rs/zerolog" + + commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" +) + +func LogSubDetails( + l zerolog.Logger, + subscription contracts.Subscription, + subID string, + coordinator contracts.Coordinator, +) { + log := l.Info(). + Str("Coordinator", coordinator.Address()). + Str("Link Balance", (*commonassets.Link)(subscription.Balance).Link()). + Str("Subscription ID", subID). + Str("Subscription Owner", subscription.SubOwner.String()). + Interface("Subscription Consumers", subscription.Consumers) + if subscription.NativeBalance != nil { + log = log.Str("Native Token Balance", assets.FormatWei(subscription.NativeBalance)) + } + log.Msg("Subscription Data") +} + +func LogRandomnessRequestedEvent( + l zerolog.Logger, + coordinator contracts.Coordinator, + randomWordsRequestedEvent *contracts.CoordinatorRandomWordsRequested, + isNativeBilling bool, +) { + l.Info(). + Str("Coordinator", coordinator.Address()). + Bool("Native Billing", isNativeBilling). + Str("Request ID", randomWordsRequestedEvent.RequestId.String()). + Str("Subscription ID", randomWordsRequestedEvent.SubId). + Str("Sender Address", randomWordsRequestedEvent.Sender.String()). + Str("Keyhash", fmt.Sprintf("0x%x", randomWordsRequestedEvent.KeyHash)). + Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). + Uint32("Number of Words", randomWordsRequestedEvent.NumWords). + Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). + Str("TX Hash", randomWordsRequestedEvent.Raw.TxHash.String()). + Uint64("BlockNumber", randomWordsRequestedEvent.Raw.BlockNumber). + Str("BlockHash", randomWordsRequestedEvent.Raw.BlockHash.String()). + Msg("RandomnessRequested Event") +} + +func LogRandomWordsFulfilledEvent( + l zerolog.Logger, + coordinator contracts.Coordinator, + randomWordsFulfilledEvent *contracts.CoordinatorRandomWordsFulfilled, + isNativeBilling bool, +) { + l.Info(). + Bool("Native Billing", isNativeBilling). + Str("Coordinator", coordinator.Address()). + Str("Total Payment", randomWordsFulfilledEvent.Payment.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Str("Subscription ID", randomWordsFulfilledEvent.SubId). + Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). + Bool("Success", randomWordsFulfilledEvent.Success). + Uint64("BlockNumber", randomWordsFulfilledEvent.Raw.BlockNumber). + Str("BlockHash", randomWordsFulfilledEvent.Raw.BlockHash.String()). + Msg("RandomWordsFulfilled Event (TX metadata)") +} + +func LogFulfillmentDetailsLinkBilling( + l zerolog.Logger, + wrapperConsumerJuelsBalanceBeforeRequest *big.Int, + wrapperConsumerJuelsBalanceAfterRequest *big.Int, + consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, + randomWordsFulfilledEvent *contracts.CoordinatorRandomWordsFulfilled, +) { + l.Info(). + Str("Consumer Balance Before Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()). + Str("Consumer Balance After Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()). + Bool("Fulfilment Status", consumerStatus.Fulfilled). + Str("Paid by Consumer Contract (Link)", (*commonassets.Link)(consumerStatus.Paid).Link()). + Str("Paid by Coordinator Sub (Link)", (*commonassets.Link)(randomWordsFulfilledEvent.Payment).Link()). + Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). + Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). + Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). + Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Msg("Random Words Fulfilment Details For Link Billing") +} + +func LogFulfillmentDetailsNativeBilling( + l zerolog.Logger, + wrapperConsumerBalanceBeforeRequestWei *big.Int, + wrapperConsumerBalanceAfterRequestWei *big.Int, + consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, + randomWordsFulfilledEvent *contracts.CoordinatorRandomWordsFulfilled, +) { + l.Info(). + Str("Consumer Balance Before Request", assets.FormatWei(wrapperConsumerBalanceBeforeRequestWei)). + Str("Consumer Balance After Request", assets.FormatWei(wrapperConsumerBalanceAfterRequestWei)). + Bool("Fulfilment Status", consumerStatus.Fulfilled). + Str("Paid by Consumer Contract", assets.FormatWei(consumerStatus.Paid)). + Str("Paid by Coordinator Sub", assets.FormatWei(randomWordsFulfilledEvent.Payment)). + Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). + Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). + Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). + Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). + Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). + Msg("Random Words Request Fulfilment Details For Native Billing") +} + +func LogRandomWordsForcedEvent( + l zerolog.Logger, + vrfOwner contracts.VRFOwner, + randomWordsForcedEvent *vrf_owner.VRFOwnerRandomWordsForced, +) { + l.Debug(). + Str("VRFOwner", vrfOwner.Address()). + Uint64("Sub ID", randomWordsForcedEvent.SubId). + Str("TX Hash", randomWordsForcedEvent.Raw.TxHash.String()). + Str("Request ID", randomWordsForcedEvent.RequestId.String()). + Str("Sender", randomWordsForcedEvent.Sender.String()). + Msg("RandomWordsForced Event (TX metadata)") +} diff --git a/integration-tests/actions/vrf/vrfv2/contract_steps.go b/integration-tests/actions/vrf/vrfv2/contract_steps.go index 46b84eb836b..bd4535ebf77 100644 --- a/integration-tests/actions/vrf/vrfv2/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2/contract_steps.go @@ -452,7 +452,7 @@ func FundVRFCoordinatorV2Subscription( func DirectFundingRequestRandomnessAndWaitForFulfillment( l zerolog.Logger, consumer contracts.VRFv2WrapperLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2, + coordinator contracts.Coordinator, subID uint64, vrfv2KeyData *vrfcommon.VRFKeyData, minimumConfirmations uint16, @@ -461,7 +461,7 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequest uint16, randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, -) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsFulfilled, error) { logRandRequest( l, consumer.Address(), @@ -496,7 +496,7 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( func RequestRandomnessAndWaitForFulfillment( l zerolog.Logger, consumer contracts.VRFv2LoadTestConsumer, - coordinator contracts.VRFCoordinatorV2, + coordinator contracts.Coordinator, subID uint64, vrfKeyData *vrfcommon.VRFKeyData, minimumConfirmations uint16, @@ -505,7 +505,7 @@ func RequestRandomnessAndWaitForFulfillment( randomnessRequestCountPerRequest uint16, randomnessRequestCountPerRequestDeviation uint16, randomWordsFulfilledEventTimeout time.Duration, -) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsRequestedEvent, err := RequestRandomness( l, consumer, @@ -536,7 +536,7 @@ func RequestRandomnessAndWaitForFulfillment( func RequestRandomness( l zerolog.Logger, consumer contracts.VRFv2LoadTestConsumer, - coordinator contracts.VRFCoordinatorV2, + coordinator contracts.Coordinator, subID uint64, vrfKeyData *vrfcommon.VRFKeyData, minimumConfirmations uint16, @@ -544,7 +544,7 @@ func RequestRandomness( numberOfWords uint32, randomnessRequestCountPerRequest uint16, randomnessRequestCountPerRequestDeviation uint16, -) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) { +) (*contracts.CoordinatorRandomWordsRequested, error) { logRandRequest( l, consumer.Address(), @@ -569,7 +569,7 @@ func RequestRandomness( if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRequestRandomness, err) } - LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent) + vrfcommon.LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, false) return randomWordsRequestedEvent, err } @@ -577,7 +577,7 @@ func RequestRandomness( func RequestRandomnessWithForceFulfillAndWaitForFulfillment( l zerolog.Logger, consumer contracts.VRFv2LoadTestConsumer, - coordinator contracts.VRFCoordinatorV2, + coordinator contracts.Coordinator, vrfOwner contracts.VRFOwner, vrfv2KeyData *vrfcommon.VRFKeyData, minimumConfirmations uint16, @@ -588,9 +588,10 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( subTopUpAmount *big.Int, linkAddress common.Address, randomWordsFulfilledEventTimeout time.Duration, -) (*vrf_coordinator_v2.VRFCoordinatorV2ConfigSet, *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, *vrf_owner.VRFOwnerRandomWordsForced, error) { +) (*contracts.CoordinatorConfigSet, *contracts.CoordinatorRandomWordsFulfilled, *vrf_owner.VRFOwnerRandomWordsForced, error) { logRandRequest(l, consumer.Address(), coordinator.Address(), 0, minimumConfirmations, callbackGasLimit, numberOfWords, randomnessRequestCountPerRequest, randomnessRequestCountPerRequestDeviation, vrfv2KeyData.KeyHash) - _, err := consumer.RequestRandomWordsWithForceFulfill( + randomWordsRequestedEvent, err := consumer.RequestRandomWordsWithForceFulfill( + coordinator, vrfv2KeyData.KeyHash, minimumConfirmations, callbackGasLimit, @@ -603,20 +604,11 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRequestRandomness, err) } - randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfv2KeyData.KeyHash}, - nil, - []common.Address{common.HexToAddress(consumer.Address())}, - time.Minute*1, - ) - if err != nil { - return nil, nil, nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsRequestedEvent, err) - } - LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent) + vrfcommon.LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, false) errorChannel := make(chan error) - configSetEventChannel := make(chan *vrf_coordinator_v2.VRFCoordinatorV2ConfigSet) - randWordsFulfilledEventChannel := make(chan *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled) + configSetEventChannel := make(chan *contracts.CoordinatorConfigSet) + randWordsFulfilledEventChannel := make(chan *contracts.CoordinatorRandomWordsFulfilled) randWordsForcedEventChannel := make(chan *vrf_owner.VRFOwnerRandomWordsForced) go func() { @@ -632,8 +624,10 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( go func() { randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( - []*big.Int{randomWordsRequestedEvent.RequestId}, - randomWordsFulfilledEventTimeout, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + Timeout: randomWordsFulfilledEventTimeout, + }, ) if err != nil { l.Error().Err(err).Msg("error waiting for RandomWordsFulfilledEvent") @@ -656,8 +650,8 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( randWordsForcedEventChannel <- randomWordsForcedEvent }() - var configSetEvent *vrf_coordinator_v2.VRFCoordinatorV2ConfigSet - var randomWordsFulfilledEvent *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled + var configSetEvent *contracts.CoordinatorConfigSet + var randomWordsFulfilledEvent *contracts.CoordinatorRandomWordsFulfilled var randomWordsForcedEvent *vrf_owner.VRFOwnerRandomWordsForced for i := 0; i < 3; i++ { select { @@ -665,9 +659,9 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( return nil, nil, nil, err case configSetEvent = <-configSetEventChannel: case randomWordsFulfilledEvent = <-randWordsFulfilledEventChannel: - LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent) + vrfcommon.LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, false) case randomWordsForcedEvent = <-randWordsForcedEventChannel: - LogRandomWordsForcedEvent(l, vrfOwner, randomWordsForcedEvent) + vrfcommon.LogRandomWordsForcedEvent(l, vrfOwner, randomWordsForcedEvent) case <-time.After(randomWordsFulfilledEventTimeout): err = fmt.Errorf("timeout waiting for ConfigSet, RandomWordsFulfilled and RandomWordsForced events") } @@ -676,19 +670,21 @@ func RequestRandomnessWithForceFulfillAndWaitForFulfillment( } func WaitRandomWordsFulfilledEvent( - coordinator contracts.VRFCoordinatorV2, + coordinator contracts.Coordinator, requestId *big.Int, randomWordsFulfilledEventTimeout time.Duration, l zerolog.Logger, -) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { +) (*contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( - []*big.Int{requestId}, - randomWordsFulfilledEventTimeout, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{requestId}, + Timeout: randomWordsFulfilledEventTimeout, + }, ) if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsFulfilledEvent, err) } - LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent) + vrfcommon.LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, false) return randomWordsFulfilledEvent, err } diff --git a/integration-tests/actions/vrf/vrfv2/logging_helpers.go b/integration-tests/actions/vrf/vrfv2/logging_helpers.go index 82c45267aaf..248eebf45f1 100644 --- a/integration-tests/actions/vrf/vrfv2/logging_helpers.go +++ b/integration-tests/actions/vrf/vrfv2/logging_helpers.go @@ -4,73 +4,8 @@ import ( "fmt" "github.com/rs/zerolog" - - commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" - "github.com/smartcontractkit/chainlink/integration-tests/contracts" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_owner" ) -func LogSubDetails(l zerolog.Logger, subscription vrf_coordinator_v2.GetSubscription, subID uint64, coordinator contracts.VRFCoordinatorV2) { - l.Debug(). - Str("Coordinator", coordinator.Address()). - Str("Link Balance", (*commonassets.Link)(subscription.Balance).Link()). - Uint64("Subscription ID", subID). - Str("Subscription Owner", subscription.Owner.String()). - Interface("Subscription Consumers", subscription.Consumers). - Msg("Subscription Data") -} - -func LogRandomnessRequestedEvent( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2, - randomWordsRequestedEvent *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, -) { - l.Info(). - Str("Coordinator", coordinator.Address()). - Str("Request ID", randomWordsRequestedEvent.RequestId.String()). - Uint64("Subscription ID", randomWordsRequestedEvent.SubId). - Str("Sender Address", randomWordsRequestedEvent.Sender.String()). - Str("Keyhash", fmt.Sprintf("0x%x", randomWordsRequestedEvent.KeyHash)). - Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). - Uint32("Number of Words", randomWordsRequestedEvent.NumWords). - Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). - Str("TX Hash", randomWordsRequestedEvent.Raw.TxHash.String()). - Uint64("BlockNumber", randomWordsRequestedEvent.Raw.BlockNumber). - Str("BlockHash", randomWordsRequestedEvent.Raw.BlockHash.String()). - Msg("RandomnessRequested Event") -} - -func LogRandomWordsFulfilledEvent( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2, - randomWordsFulfilledEvent *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, -) { - l.Info(). - Str("Coordinator", coordinator.Address()). - Str("Total Payment", randomWordsFulfilledEvent.Payment.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). - Bool("Success", randomWordsFulfilledEvent.Success). - Uint64("BlockNumber", randomWordsFulfilledEvent.Raw.BlockNumber). - Str("BlockHash", randomWordsFulfilledEvent.Raw.BlockHash.String()). - Msg("RandomWordsFulfilled Event (TX metadata)") -} - -func LogRandomWordsForcedEvent( - l zerolog.Logger, - vrfOwner contracts.VRFOwner, - randomWordsForcedEvent *vrf_owner.VRFOwnerRandomWordsForced, -) { - l.Debug(). - Str("VRFOwner", vrfOwner.Address()). - Uint64("Sub ID", randomWordsForcedEvent.SubId). - Str("TX Hash", randomWordsForcedEvent.Raw.TxHash.String()). - Str("Request ID", randomWordsForcedEvent.RequestId.String()). - Str("Sender", randomWordsForcedEvent.Sender.String()). - Msg("RandomWordsForced Event (TX metadata)") -} - func logRandRequest( l zerolog.Logger, consumer string, diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index acc509fb58b..77937dd8de9 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -19,8 +19,6 @@ import ( tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" chainlinkutils "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" ) func DeployVRFV2_5Contracts( @@ -93,6 +91,7 @@ func VRFV2_5RegisterProvingKey( func VRFV2PlusUpgradedVersionRegisterProvingKey( vrfKey *client.VRFKey, coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, + gasLaneMaxGasPrice uint64, ) (vrfcommon.VRFEncodedProvingKey, error) { provingKey, err := actions.EncodeOnChainVRFProvingKey(*vrfKey) if err != nil { @@ -100,6 +99,7 @@ func VRFV2PlusUpgradedVersionRegisterProvingKey( } err = coordinator.RegisterProvingKey( provingKey, + gasLaneMaxGasPrice, ) if err != nil { return vrfcommon.VRFEncodedProvingKey{}, fmt.Errorf("%s, err %w", vrfcommon.ErrRegisterProvingKey, err) @@ -331,15 +331,15 @@ func GetCoordinatorTotalBalance(coordinator contracts.VRFCoordinatorV2_5) (linkT return } -func RequestRandomnessAndWaitForRequestedEvent( +func RequestRandomness( consumer contracts.VRFv2PlusLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2_5, + coordinator contracts.Coordinator, vrfKeyData *vrfcommon.VRFKeyData, subID *big.Int, isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger, -) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, error) { +) (*contracts.CoordinatorRandomWordsRequested, error) { LogRandRequest( l, consumer.Address(), @@ -349,154 +349,95 @@ func RequestRandomnessAndWaitForRequestedEvent( vrfKeyData.KeyHash, config, ) - ch := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested) - errorChannel := make(chan error) - go func() { - _, err := consumer.RequestRandomness( - vrfKeyData.KeyHash, - subID, - *config.MinimumConfirmations, - *config.CallbackGasLimit, - isNativeBilling, - *config.NumberOfWords, - *config.RandomnessRequestCountPerRequest, - ) - if err != nil { - l.Error().Err(err).Msg(err.Error()) - errorChannel <- err - } - }() - go func() { - randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKeyData.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumer.Address())}, - time.Minute*1, - ) - if err != nil { - l.Error().Err(err).Msg("error waiting for RandomnessRequested events") - errorChannel <- err - } - LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling) - ch <- randomWordsRequestedEvent - }() - for { - select { - case err := <-errorChannel: - return nil, err - case event := <-ch: - return event, nil - case <-time.After(config.RandomWordsFulfilledEventTimeout.Duration): - return nil, fmt.Errorf("timeout waiting for RandomnessRequested events") - } - } -} - -func RequestRandomnessAndWaitForFulfillment( - consumer contracts.VRFv2PlusLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2_5, - vrfKeyData *vrfcommon.VRFKeyData, - subID *big.Int, - isNativeBilling bool, - config *vrfv2plus_config.General, - l zerolog.Logger, -) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { - LogRandRequest( - l, - consumer.Address(), - coordinator.Address(), + randomWordsRequestedEvent, err := consumer.RequestRandomness( + coordinator, + vrfKeyData.KeyHash, subID, + *config.MinimumConfirmations, + *config.CallbackGasLimit, isNativeBilling, - vrfKeyData.KeyHash, - config, + *config.NumberOfWords, + *config.RandomnessRequestCountPerRequest, ) - ch := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled) - errorChannel := make(chan error) - go func() { - _, err := consumer.RequestRandomness( - vrfKeyData.KeyHash, - subID, - *config.MinimumConfirmations, - *config.CallbackGasLimit, - isNativeBilling, - *config.NumberOfWords, - *config.RandomnessRequestCountPerRequest, - ) - if err != nil { - l.Error().Err(err).Msg(err.Error()) - errorChannel <- err - } - }() - go func() { - fulfillmentEvents, err := WaitForRequestAndFulfillmentEvents( - consumer.Address(), - coordinator, - vrfKeyData, - subID, - isNativeBilling, - config.RandomWordsFulfilledEventTimeout.Duration, - l, - ) - if err != nil { - l.Error().Err(err).Msg("error waiting for RandomnessRequested and RandomWordsFulfilled events") - errorChannel <- err - } - ch <- fulfillmentEvents - }() - for { - select { - case err := <-errorChannel: - return nil, err - case fulfillmentEvent := <-ch: - return fulfillmentEvent, nil - case <-time.After(config.RandomWordsFulfilledEventTimeout.Duration): - return nil, fmt.Errorf("timeout waiting for RandomnessRequested and RandomWordsFulfilled events") - } + if err != nil { + return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRequestRandomness, err) } + vrfcommon.LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling) + + return randomWordsRequestedEvent, err } -func RequestRandomnessAndWaitForFulfillmentUpgraded( +func RequestRandomnessAndWaitForFulfillment( consumer contracts.VRFv2PlusLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, + coordinator contracts.Coordinator, vrfKeyData *vrfcommon.VRFKeyData, subID *big.Int, isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger, -) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { - LogRandRequest( - l, - consumer.Address(), - coordinator.Address(), +) (*contracts.CoordinatorRandomWordsFulfilled, error) { + randomWordsRequestedEvent, err := RequestRandomness( + consumer, + coordinator, + vrfKeyData, subID, isNativeBilling, - vrfKeyData.KeyHash, config, - ) - _, err := consumer.RequestRandomness( - vrfKeyData.KeyHash, - subID, - *config.MinimumConfirmations, - *config.CallbackGasLimit, - isNativeBilling, - *config.NumberOfWords, - *config.RandomnessRequestCountPerRequest, + l, ) if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRequestRandomness, err) + return nil, err } - return WaitForRequestAndFulfillmentEventsUpgraded( - consumer.Address(), + randomWordsFulfilledEvent, err := WaitRandomWordsFulfilledEvent( coordinator, - vrfKeyData, + randomWordsRequestedEvent.RequestId, subID, isNativeBilling, config.RandomWordsFulfilledEventTimeout.Duration, l, ) + if err != nil { + return nil, err + } + return randomWordsFulfilledEvent, nil + } +//func RequestRandomnessAndWaitForFulfillmentUpgraded( +// consumer contracts.VRFv2PlusLoadTestConsumer, +// coordinator contracts.Coordinator, +// vrfKeyData *vrfcommon.VRFKeyData, +// subID *big.Int, +// isNativeBilling bool, +// config *vrfv2plus_config.General, +// l zerolog.Logger, +//) (*contracts.CoordinatorRandomWordsFulfilled, error) { +// +// randomWordsRequestedEvent, err := RequestRandomness( +// consumer, +// coordinator, +// vrfKeyData, +// subID, +// isNativeBilling, +// config, +// l, +// ) +// +// if err != nil { +// return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrRequestRandomness, err) +// } +// +// return WaitForRandomWordsFulfilledEventUpgraded( +// coordinator, +// randomWordsRequestedEvent.RequestId, +// subID, +// isNativeBilling, +// config.RandomWordsFulfilledEventTimeout.Duration, +// l, +// ) +//} + func DeployVRFV2PlusDirectFundingContracts( contractDeployer contracts.ContractDeployer, chainClient blockchain.EVMClient, @@ -527,69 +468,66 @@ func DeployVRFV2PlusDirectFundingContracts( return &VRFV2PlusWrapperContracts{vrfv2PlusWrapper, consumers}, nil } -func WrapperRequestRandomness( - consumer contracts.VRFv2PlusWrapperLoadTestConsumer, - coordinatorAddress string, - vrfKeyData *vrfcommon.VRFKeyData, - subID *big.Int, - isNativeBilling bool, - config *vrfv2plus_config.General, - l zerolog.Logger) (string, error) { +func WrapperRequestRandomness(consumer contracts.VRFv2PlusWrapperLoadTestConsumer, coordinator contracts.Coordinator, vrfKeyData *vrfcommon.VRFKeyData, subID *big.Int, isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger) (*contracts.CoordinatorRandomWordsRequested, string, error) { LogRandRequest( l, consumer.Address(), - coordinatorAddress, + coordinator.Address(), subID, isNativeBilling, vrfKeyData.KeyHash, config, ) + var randomWordsRequestedEvent *contracts.CoordinatorRandomWordsRequested + var err error if isNativeBilling { - _, err := consumer.RequestRandomnessNative( + randomWordsRequestedEvent, err = consumer.RequestRandomnessNative( + coordinator, *config.MinimumConfirmations, *config.CallbackGasLimit, *config.NumberOfWords, *config.RandomnessRequestCountPerRequest, ) if err != nil { - return "", fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingNativePayment, err) + return nil, "", fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingNativePayment, err) } } else { - _, err := consumer.RequestRandomness( + randomWordsRequestedEvent, err = consumer.RequestRandomness( + coordinator, *config.MinimumConfirmations, *config.CallbackGasLimit, *config.NumberOfWords, *config.RandomnessRequestCountPerRequest, ) if err != nil { - return "", fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingLinkPayment, err) + return nil, "", fmt.Errorf("%s, err %w", ErrRequestRandomnessDirectFundingLinkPayment, err) } } + vrfcommon.LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling) wrapperAddress, err := consumer.GetWrapper(context.Background()) if err != nil { - return "", fmt.Errorf("error getting wrapper address, err: %w", err) + return nil, "", fmt.Errorf("error getting wrapper address, err: %w", err) } - return wrapperAddress.Hex(), nil + return randomWordsRequestedEvent, wrapperAddress.Hex(), nil } func DirectFundingRequestRandomnessAndWaitForFulfillment( consumer contracts.VRFv2PlusWrapperLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2_5, + coordinator contracts.Coordinator, vrfKeyData *vrfcommon.VRFKeyData, subID *big.Int, isNativeBilling bool, config *vrfv2plus_config.General, l zerolog.Logger, -) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { - wrapperAddress, err := WrapperRequestRandomness(consumer, coordinator.Address(), vrfKeyData, subID, +) (*contracts.CoordinatorRandomWordsFulfilled, error) { + randomWordsRequestedEvent, _, err := WrapperRequestRandomness(consumer, coordinator, vrfKeyData, subID, isNativeBilling, config, l) if err != nil { return nil, fmt.Errorf("error getting wrapper address, err: %w", err) } - return WaitForRequestAndFulfillmentEvents( - wrapperAddress, + return WaitRandomWordsFulfilledEvent( coordinator, - vrfKeyData, + randomWordsRequestedEvent.RequestId, subID, isNativeBilling, config.RandomWordsFulfilledEventTimeout.Duration, @@ -597,95 +535,26 @@ func DirectFundingRequestRandomnessAndWaitForFulfillment( ) } -func DirectFundingRequestRandomnessAndWaitForFulfillmentUpgraded( - consumer contracts.VRFv2PlusWrapperLoadTestConsumer, - coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, - vrfKeyData *vrfcommon.VRFKeyData, - subID *big.Int, - isNativeBilling bool, - config *vrfv2plus_config.General, - l zerolog.Logger, -) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { - wrapperAddress, err := WrapperRequestRandomness(consumer, coordinator.Address(), vrfKeyData, subID, - isNativeBilling, config, l) - if err != nil { - return nil, fmt.Errorf("error getting wrapper address, err: %w", err) - } - return WaitForRequestAndFulfillmentEventsUpgraded( - wrapperAddress, - coordinator, - vrfKeyData, - subID, - isNativeBilling, - config.RandomWordsFulfilledEventTimeout.Duration, - l, - ) -} - -func WaitForRequestAndFulfillmentEvents( - consumerAddress string, - coordinator contracts.VRFCoordinatorV2_5, - vrfKeyData *vrfcommon.VRFKeyData, +func WaitRandomWordsFulfilledEvent( + coordinator contracts.Coordinator, + requestId *big.Int, subID *big.Int, isNativeBilling bool, randomWordsFulfilledEventTimeout time.Duration, l zerolog.Logger, -) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { - randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKeyData.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumerAddress)}, - time.Minute*1, - ) - if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsRequestedEvent, err) - } - - LogRandomnessRequestedEvent(l, coordinator, randomWordsRequestedEvent, isNativeBilling) - +) (*contracts.CoordinatorRandomWordsFulfilled, error) { randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( - []*big.Int{subID}, - []*big.Int{randomWordsRequestedEvent.RequestId}, - randomWordsFulfilledEventTimeout, + contracts.RandomWordsFulfilledEventFilter{ + SubIDs: []*big.Int{subID}, + RequestIds: []*big.Int{requestId}, + Timeout: randomWordsFulfilledEventTimeout, + }, ) if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsFulfilledEvent, err) } - LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, isNativeBilling) - return randomWordsFulfilledEvent, err -} - -func WaitForRequestAndFulfillmentEventsUpgraded( - consumerAddress string, - coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, - vrfKeyData *vrfcommon.VRFKeyData, - subID *big.Int, - isNativeBilling bool, - randomWordsFulfilledEventTimeout time.Duration, - l zerolog.Logger, -) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { - randomWordsRequestedEvent, err := coordinator.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKeyData.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumerAddress)}, - time.Minute*1, - ) - if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsRequestedEvent, err) - } - - LogRandomnessRequestedEventUpgraded(l, coordinator, randomWordsRequestedEvent, isNativeBilling) - - randomWordsFulfilledEvent, err := coordinator.WaitForRandomWordsFulfilledEvent( - []*big.Int{subID}, - []*big.Int{randomWordsRequestedEvent.RequestId}, - randomWordsFulfilledEventTimeout, - ) - if err != nil { - return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitRandomWordsFulfilledEvent, err) - } - LogRandomWordsFulfilledEventUpgraded(l, coordinator, randomWordsFulfilledEvent, isNativeBilling) + vrfcommon.LogRandomWordsFulfilledEvent(l, coordinator, randomWordsFulfilledEvent, isNativeBilling) return randomWordsFulfilledEvent, err } diff --git a/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go b/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go index 995af9ee76c..b613298f1fd 100644 --- a/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go +++ b/integration-tests/actions/vrf/vrfv2plus/logging_helpers.go @@ -6,165 +6,12 @@ import ( "github.com/rs/zerolog" - commonassets "github.com/smartcontractkit/chainlink-common/pkg/assets" - vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/contracts" vrfv2plus_config "github.com/smartcontractkit/chainlink/integration-tests/testconfig/vrfv2plus" - "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_v2plus_upgraded_version" - "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrfv2plus_wrapper_load_test_consumer" ) -func LogSubDetails(l zerolog.Logger, subscription vrf_coordinator_v2_5.GetSubscription, subID *big.Int, coordinator contracts.VRFCoordinatorV2_5) { - l.Debug(). - Str("Coordinator", coordinator.Address()). - Str("Link Balance", (*commonassets.Link)(subscription.Balance).Link()). - Str("Native Token Balance", assets.FormatWei(subscription.NativeBalance)). - Str("Subscription ID", subID.String()). - Str("Subscription Owner", subscription.SubOwner.String()). - Interface("Subscription Consumers", subscription.Consumers). - Msg("Subscription Data") -} - -func LogRandomnessRequestedEventUpgraded( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, - randomWordsRequestedEvent *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested, - isNativeBilling bool, -) { - l.Debug(). - Str("Coordinator", coordinator.Address()). - Bool("Native Billing", isNativeBilling). - Str("Request ID", randomWordsRequestedEvent.RequestId.String()). - Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). - Str("Sender Address", randomWordsRequestedEvent.Sender.String()). - Str("Keyhash", fmt.Sprintf("0x%x", randomWordsRequestedEvent.KeyHash)). - Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). - Uint32("Number of Words", randomWordsRequestedEvent.NumWords). - Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). - Msg("RandomnessRequested Event") -} - -func LogRandomWordsFulfilledEventUpgraded( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, - randomWordsFulfilledEvent *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, - isNativeBilling bool, -) { - l.Debug(). - Str("Coordinator", coordinator.Address()). - Bool("Native Billing", isNativeBilling). - Str("Total Payment in Juels", randomWordsFulfilledEvent.Payment.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Str("Subscription ID", randomWordsFulfilledEvent.SubID.String()). - Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). - Bool("Success", randomWordsFulfilledEvent.Success). - Msg("RandomWordsFulfilled Event (TX metadata)") -} - -func LogRandomnessRequestedEvent( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2_5, - randomWordsRequestedEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, - isNativeBilling bool, -) { - l.Info(). - Str("Coordinator", coordinator.Address()). - Bool("Native Billing", isNativeBilling). - Str("Request ID", randomWordsRequestedEvent.RequestId.String()). - Str("Subscription ID", randomWordsRequestedEvent.SubId.String()). - Str("Sender Address", randomWordsRequestedEvent.Sender.String()). - Str("Keyhash", fmt.Sprintf("0x%x", randomWordsRequestedEvent.KeyHash)). - Uint32("Callback Gas Limit", randomWordsRequestedEvent.CallbackGasLimit). - Uint32("Number of Words", randomWordsRequestedEvent.NumWords). - Uint16("Minimum Request Confirmations", randomWordsRequestedEvent.MinimumRequestConfirmations). - Str("TX Hash", randomWordsRequestedEvent.Raw.TxHash.String()). - Uint64("BlockNumber", randomWordsRequestedEvent.Raw.BlockNumber). - Str("BlockHash", randomWordsRequestedEvent.Raw.BlockHash.String()). - Msg("RandomnessRequested Event") -} - -func LogRandomWordsFulfilledEvent( - l zerolog.Logger, - coordinator contracts.VRFCoordinatorV2_5, - randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, - isNativeBilling bool, -) { - l.Info(). - Bool("Native Billing", isNativeBilling). - Str("Coordinator", coordinator.Address()). - Str("Total Payment", randomWordsFulfilledEvent.Payment.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Str("Subscription ID", randomWordsFulfilledEvent.SubId.String()). - Str("Request ID", randomWordsFulfilledEvent.RequestId.String()). - Bool("Success", randomWordsFulfilledEvent.Success). - Uint64("BlockNumber", randomWordsFulfilledEvent.Raw.BlockNumber). - Str("BlockHash", randomWordsFulfilledEvent.Raw.BlockHash.String()). - Msg("RandomWordsFulfilled Event (TX metadata)") -} - -func LogMigrationCompletedEvent(l zerolog.Logger, migrationCompletedEvent *vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, vrfv2PlusContracts *vrfcommon.VRFContracts) { - l.Info(). - Str("Subscription ID", migrationCompletedEvent.SubId.String()). - Str("Migrated From Coordinator", vrfv2PlusContracts.CoordinatorV2Plus.Address()). - Str("Migrated To Coordinator", migrationCompletedEvent.NewCoordinator.String()). - Msg("MigrationCompleted Event") -} - -func LogSubDetailsAfterMigration(l zerolog.Logger, newCoordinator contracts.VRFCoordinatorV2PlusUpgradedVersion, subID *big.Int, migratedSubscription vrf_v2plus_upgraded_version.GetSubscription) { - l.Info(). - Str("New Coordinator", newCoordinator.Address()). - Str("Subscription ID", subID.String()). - Str("Juels Balance", migratedSubscription.Balance.String()). - Str("Native Token Balance", migratedSubscription.NativeBalance.String()). - Str("Subscription Owner", migratedSubscription.SubOwner.String()). - Interface("Subscription Consumers", migratedSubscription.Consumers). - Msg("Subscription Data After Migration to New Coordinator") -} - -func LogFulfillmentDetailsLinkBilling( - l zerolog.Logger, - wrapperConsumerJuelsBalanceBeforeRequest *big.Int, - wrapperConsumerJuelsBalanceAfterRequest *big.Int, - consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, - randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, -) { - l.Info(). - Str("Consumer Balance Before Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceBeforeRequest).Link()). - Str("Consumer Balance After Request (Link)", (*commonassets.Link)(wrapperConsumerJuelsBalanceAfterRequest).Link()). - Bool("Fulfilment Status", consumerStatus.Fulfilled). - Str("Paid by Consumer Contract (Link)", (*commonassets.Link)(consumerStatus.Paid).Link()). - Str("Paid by Coordinator Sub (Link)", (*commonassets.Link)(randomWordsFulfilledEvent.Payment).Link()). - Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). - Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). - Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). - Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Msg("Random Words Fulfilment Details For Link Billing") -} - -func LogFulfillmentDetailsNativeBilling( - l zerolog.Logger, - wrapperConsumerBalanceBeforeRequestWei *big.Int, - wrapperConsumerBalanceAfterRequestWei *big.Int, - consumerStatus vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, - randomWordsFulfilledEvent *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, -) { - l.Info(). - Str("Consumer Balance Before Request", assets.FormatWei(wrapperConsumerBalanceBeforeRequestWei)). - Str("Consumer Balance After Request", assets.FormatWei(wrapperConsumerBalanceAfterRequestWei)). - Bool("Fulfilment Status", consumerStatus.Fulfilled). - Str("Paid by Consumer Contract", assets.FormatWei(consumerStatus.Paid)). - Str("Paid by Coordinator Sub", assets.FormatWei(randomWordsFulfilledEvent.Payment)). - Str("RequestTimestamp", consumerStatus.RequestTimestamp.String()). - Str("FulfilmentTimestamp", consumerStatus.FulfilmentTimestamp.String()). - Str("RequestBlockNumber", consumerStatus.RequestBlockNumber.String()). - Str("FulfilmentBlockNumber", consumerStatus.FulfilmentBlockNumber.String()). - Str("TX Hash", randomWordsFulfilledEvent.Raw.TxHash.String()). - Msg("Random Words Request Fulfilment Details For Native Billing") -} - func LogRandRequest( l zerolog.Logger, consumer string, @@ -186,3 +33,22 @@ func LogRandRequest( Uint16("RandomnessRequestCountPerRequestDeviation", *config.RandomnessRequestCountPerRequestDeviation). Msg("Requesting randomness") } + +func LogMigrationCompletedEvent(l zerolog.Logger, migrationCompletedEvent *vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, coordinator contracts.Coordinator) { + l.Info(). + Str("Subscription ID", migrationCompletedEvent.SubId.String()). + Str("Migrated From Coordinator", coordinator.Address()). + Str("Migrated To Coordinator", migrationCompletedEvent.NewCoordinator.String()). + Msg("MigrationCompleted Event") +} + +func LogSubDetailsAfterMigration(l zerolog.Logger, newCoordinator contracts.Coordinator, subID *big.Int, migratedSubscription vrf_v2plus_upgraded_version.GetSubscription) { + l.Info(). + Str("New Coordinator", newCoordinator.Address()). + Str("Subscription ID", subID.String()). + Str("Juels Balance", migratedSubscription.Balance.String()). + Str("Native Token Balance", migratedSubscription.NativeBalance.String()). + Str("Subscription Owner", migratedSubscription.SubOwner.String()). + Interface("Subscription Consumers", migratedSubscription.Consumers). + Msg("Subscription Data After Migration to New Coordinator") +} diff --git a/integration-tests/contracts/contract_vrf_models.go b/integration-tests/contracts/contract_vrf_models.go index 4dff9c98b61..e23149c7de4 100644 --- a/integration-tests/contracts/contract_vrf_models.go +++ b/integration-tests/contracts/contract_vrf_models.go @@ -60,23 +60,23 @@ type VRFCoordinatorV2 interface { CreateSubscription() (*types.Transaction, error) AddConsumer(subId uint64, consumerAddress string) error Address() string - GetSubscription(ctx context.Context, subID uint64) (vrf_coordinator_v2.GetSubscription, error) + GetSubscription(ctx context.Context, subID uint64) (Subscription, error) GetOwner(ctx context.Context) (common.Address, error) PendingRequestsExist(ctx context.Context, subID uint64) (bool, error) OwnerCancelSubscription(subID uint64) (*types.Transaction, error) ParseSubscriptionCanceled(log types.Log) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled, error) - ParseRandomWordsRequested(log types.Log) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) + ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) ParseLog(log types.Log) (generated.AbigenLog, error) CancelSubscription(subID uint64, to common.Address) (*types.Transaction, error) FindSubscriptionID(subID uint64) (uint64, error) - WaitForRandomWordsFulfilledEvent(requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) + WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []uint64, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) WaitForSubscriptionCanceledEvent(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCanceled, error) WaitForSubscriptionConsumerAdded(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionConsumerAdded, error) WaitForSubscriptionConsumerRemoved(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionConsumerRemoved, error) WaitForSubscriptionCreatedEvent(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionCreated, error) WaitForSubscriptionFunded(subID []uint64, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2SubscriptionFunded, error) - WaitForConfigSetEvent(timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2ConfigSet, error) + WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) OracleWithdraw(recipient common.Address, amount *big.Int) error } @@ -109,7 +109,7 @@ type VRFCoordinatorV2_5 interface { FundSubscriptionWithNative(subId *big.Int, nativeTokenAmount *big.Int) error Address() string PendingRequestsExist(ctx context.Context, subID *big.Int) (bool, error) - GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error) + GetSubscription(ctx context.Context, subID *big.Int) (Subscription, error) OwnerCancelSubscription(subID *big.Int) (*types.Transaction, error) CancelSubscription(subID *big.Int, to common.Address) (*types.Transaction, error) Withdraw(recipient common.Address) error @@ -119,9 +119,10 @@ type VRFCoordinatorV2_5 interface { FindSubscriptionID(subID *big.Int) (*big.Int, error) WaitForSubscriptionCreatedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCreated, error) WaitForSubscriptionCanceledEvent(subID *big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25SubscriptionCanceled, error) - WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) - WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, error) + WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForMigrationCompletedEvent(timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25MigrationCompleted, error) + ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) } type VRFCoordinatorV2PlusUpgradedVersion interface { @@ -142,6 +143,7 @@ type VRFCoordinatorV2PlusUpgradedVersion interface { ) error RegisterProvingKey( publicProvingKey [2]*big.Int, + gasLaneMaxGasPrice uint64, ) error HashOfKey(ctx context.Context, pubKey [2]*big.Int) ([32]byte, error) CreateSubscription() error @@ -155,9 +157,10 @@ type VRFCoordinatorV2PlusUpgradedVersion interface { GetSubscription(ctx context.Context, subID *big.Int) (vrf_v2plus_upgraded_version.GetSubscription, error) GetActiveSubscriptionIds(ctx context.Context, startIndex *big.Int, maxCount *big.Int) ([]*big.Int, error) FindSubscriptionID() (*big.Int, error) - WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) + WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) WaitForMigrationCompletedEvent(timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionMigrationCompleted, error) - WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested, error) + ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) } type VRFV2Wrapper interface { @@ -211,15 +214,16 @@ type VRFv2Consumer interface { type VRFv2LoadTestConsumer interface { Address() string RequestRandomness( - coordinator VRFCoordinatorV2, + coordinator Coordinator, keyHash [32]byte, subID uint64, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16, - ) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) + ) (*CoordinatorRandomWordsRequested, error) RequestRandomWordsWithForceFulfill( + coordinator Coordinator, keyHash [32]byte, requestConfirmations uint16, callbackGasLimit uint32, @@ -227,7 +231,7 @@ type VRFv2LoadTestConsumer interface { requestCount uint16, subTopUpAmount *big.Int, linkAddress common.Address, - ) (*types.Transaction, error) + ) (*CoordinatorRandomWordsRequested, error) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrf_load_test_with_metrics.GetRequestStatus, error) GetLastRequestId(ctx context.Context) (*big.Int, error) GetLoadTestMetrics(ctx context.Context) (*VRFLoadTestMetrics, error) @@ -237,7 +241,7 @@ type VRFv2LoadTestConsumer interface { type VRFv2WrapperLoadTestConsumer interface { Address() string Fund(ethAmount *big.Float) error - RequestRandomness(coordinator VRFCoordinatorV2, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) + RequestRandomness(coordinator Coordinator, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*CoordinatorRandomWordsRequested, error) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrfv2_wrapper_load_test_consumer.GetRequestStatus, error) GetLastRequestId(ctx context.Context) (*big.Int, error) GetWrapper(ctx context.Context) (common.Address, error) @@ -246,7 +250,15 @@ type VRFv2WrapperLoadTestConsumer interface { type VRFv2PlusLoadTestConsumer interface { Address() string - RequestRandomness(keyHash [32]byte, subID *big.Int, requestConfirmations uint16, callbackGasLimit uint32, nativePayment bool, numWords uint32, requestCount uint16) (*types.Transaction, error) + RequestRandomness( + coordinator Coordinator, + keyHash [32]byte, subID *big.Int, + requestConfirmations uint16, + callbackGasLimit uint32, + nativePayment bool, + numWords uint32, + requestCount uint16, + ) (*CoordinatorRandomWordsRequested, error) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrf_v2plus_load_test_with_metrics.GetRequestStatus, error) GetLastRequestId(ctx context.Context) (*big.Int, error) GetLoadTestMetrics(ctx context.Context) (*VRFLoadTestMetrics, error) @@ -257,8 +269,20 @@ type VRFv2PlusLoadTestConsumer interface { type VRFv2PlusWrapperLoadTestConsumer interface { Address() string Fund(ethAmount *big.Float) error - RequestRandomness(requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*types.Transaction, error) - RequestRandomnessNative(requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*types.Transaction, error) + RequestRandomness( + coordinator Coordinator, + requestConfirmations uint16, + callbackGasLimit uint32, + numWords uint32, + requestCount uint16, + ) (*CoordinatorRandomWordsRequested, error) + RequestRandomnessNative( + coordinator Coordinator, + requestConfirmations uint16, + callbackGasLimit uint32, + numWords uint32, + requestCount uint16, + ) (*CoordinatorRandomWordsRequested, error) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, error) GetLastRequestId(ctx context.Context) (*big.Int, error) GetWrapper(ctx context.Context) (common.Address, error) diff --git a/integration-tests/contracts/ethereum_vrf_common.go b/integration-tests/contracts/ethereum_vrf_common.go new file mode 100644 index 00000000000..d7eafe42a07 --- /dev/null +++ b/integration-tests/contracts/ethereum_vrf_common.go @@ -0,0 +1,124 @@ +package contracts + +import ( + "fmt" + "math/big" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + + "github.com/smartcontractkit/chainlink-testing-framework/blockchain" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/vrf_coordinator_v2_5" +) + +type Coordinator interface { + ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) + Address() string + WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) + WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) +} + +type Subscription struct { + Balance *big.Int + NativeBalance *big.Int + ReqCount uint64 + SubOwner common.Address + Consumers []common.Address +} + +type CoordinatorConfigSet struct { + MinimumRequestConfirmations uint16 + MaxGasLimit uint32 + StalenessSeconds uint32 + GasAfterPaymentCalculation uint32 + FallbackWeiPerUnitLink *big.Int + FulfillmentFlatFeeNativePPM uint32 + FulfillmentFlatFeeLinkDiscountPPM uint32 + NativePremiumPercentage uint8 + LinkPremiumPercentage uint8 + FeeConfig VRFCoordinatorV2FeeConfig + Raw types.Log +} + +type VRFCoordinatorV2FeeConfig struct { + FulfillmentFlatFeeLinkPPMTier1 uint32 + FulfillmentFlatFeeLinkPPMTier2 uint32 + FulfillmentFlatFeeLinkPPMTier3 uint32 + FulfillmentFlatFeeLinkPPMTier4 uint32 + FulfillmentFlatFeeLinkPPMTier5 uint32 + ReqsForTier2 *big.Int + ReqsForTier3 *big.Int + ReqsForTier4 *big.Int + ReqsForTier5 *big.Int +} + +type RandomWordsFulfilledEventFilter struct { + RequestIds []*big.Int + SubIDs []*big.Int + Timeout time.Duration +} + +type CoordinatorRandomWordsFulfilled struct { + RequestId *big.Int + OutputSeed *big.Int + SubId string + Payment *big.Int + NativePayment bool + Success bool + OnlyPremium bool + Raw types.Log +} + +type CoordinatorRandomWordsRequested struct { + KeyHash [32]byte + RequestId *big.Int + PreSeed *big.Int + SubId string + MinimumRequestConfirmations uint16 + CallbackGasLimit uint32 + NumWords uint32 + ExtraArgs []byte + Sender common.Address + Raw types.Log +} + +func parseRequestRandomnessLogs(coordinator Coordinator, logs []*types.Log) (*CoordinatorRandomWordsRequested, error) { + var randomWordsRequestedEvent *CoordinatorRandomWordsRequested + var err error + for _, eventLog := range logs { + for _, topic := range eventLog.Topics { + if topic.Cmp(vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested{}.Topic()) == 0 { + randomWordsRequestedEvent, err = coordinator.ParseRandomWordsRequested(*eventLog) + if err != nil { + return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) + } + } + if topic.Cmp(vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested{}.Topic()) == 0 { + randomWordsRequestedEvent, err = coordinator.ParseRandomWordsRequested(*eventLog) + if err != nil { + return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) + } + } + } + } + return randomWordsRequestedEvent, nil +} + +func RetrieveRequestRandomnessLogs(coordinator Coordinator, client blockchain.EVMClient, tx *types.Transaction) (*CoordinatorRandomWordsRequested, error) { + err := client.ProcessTransaction(tx) + if err != nil { + return nil, fmt.Errorf("ProcessTransaction failed, err: %w", err) + } + err = client.WaitForEvents() + if err != nil { + return nil, fmt.Errorf("WaitForEvents failed, err: %w", err) + } + receipt, err := client.GetTxReceipt(tx.Hash()) + if err != nil { + return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err) + } + return parseRequestRandomnessLogs(coordinator, receipt.Logs) + +} diff --git a/integration-tests/contracts/ethereum_vrfv2_contracts.go b/integration-tests/contracts/ethereum_vrfv2_contracts.go index ed99fb91109..c5116856d48 100644 --- a/integration-tests/contracts/ethereum_vrfv2_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2_contracts.go @@ -5,6 +5,7 @@ import ( "encoding/hex" "fmt" "math/big" + "strconv" "time" "github.com/ethereum/go-ethereum" @@ -248,16 +249,22 @@ func (v *EthereumVRFCoordinatorV2) HashOfKey(ctx context.Context, pubKey [2]*big return hash, nil } -func (v *EthereumVRFCoordinatorV2) GetSubscription(ctx context.Context, subID uint64) (vrf_coordinator_v2.GetSubscription, error) { +func (v *EthereumVRFCoordinatorV2) GetSubscription(ctx context.Context, subID uint64) (Subscription, error) { opts := &bind.CallOpts{ From: common.HexToAddress(v.client.GetDefaultWallet().Address()), Context: ctx, } subscription, err := v.coordinator.GetSubscription(opts, subID) if err != nil { - return vrf_coordinator_v2.GetSubscription{}, err + return Subscription{}, err } - return subscription, nil + return Subscription{ + Balance: subscription.Balance, + NativeBalance: nil, + SubOwner: subscription.Owner, + Consumers: subscription.Consumers, + ReqCount: subscription.ReqCount, + }, nil } func (v *EthereumVRFCoordinatorV2) GetOwner(ctx context.Context) (common.Address, error) { @@ -448,8 +455,24 @@ func (v *EthereumVRFCoordinatorV2) ParseSubscriptionCanceled(log types.Log) (*vr return v.coordinator.ParseSubscriptionCanceled(log) } -func (v *EthereumVRFCoordinatorV2) ParseRandomWordsRequested(log types.Log) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) { - return v.coordinator.ParseRandomWordsRequested(log) +func (v *EthereumVRFCoordinatorV2) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) { + requested, err := v.coordinator.ParseRandomWordsRequested(log) + if err != nil { + return nil, fmt.Errorf("failed to parse RandomWordsRequested event: %w", err) + } + + return &CoordinatorRandomWordsRequested{ + KeyHash: requested.KeyHash, + RequestId: requested.RequestId, + PreSeed: requested.PreSeed, + SubId: strconv.FormatUint(requested.SubId, 10), + MinimumRequestConfirmations: requested.MinimumRequestConfirmations, + CallbackGasLimit: requested.CallbackGasLimit, + NumWords: requested.NumWords, + Sender: requested.Sender, + ExtraArgs: nil, + Raw: requested.Raw, + }, nil } func (v *EthereumVRFCoordinatorV2) ParseLog(log types.Log) (generated.AbigenLog, error) { @@ -492,9 +515,9 @@ func (v *EthereumVRFCoordinatorV2) FindSubscriptionID(subID uint64) (uint64, err return subscriptionIterator.Event.SubId, nil } -func (v *EthereumVRFCoordinatorV2) WaitForRandomWordsFulfilledEvent(requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled, error) { +func (v *EthereumVRFCoordinatorV2) WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) { randomWordsFulfilledEventsChannel := make(chan *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsFulfilled) - subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, requestID) + subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, filter.RequestIds) if err != nil { return nil, err } @@ -504,10 +527,16 @@ func (v *EthereumVRFCoordinatorV2) WaitForRandomWordsFulfilledEvent(requestID [] select { case err := <-subscription.Err(): return nil, err - case <-time.After(timeout): + case <-time.After(filter.Timeout): return nil, fmt.Errorf("timeout waiting for RandomWordsFulfilled event") case randomWordsFulfilledEvent := <-randomWordsFulfilledEventsChannel: - return randomWordsFulfilledEvent, nil + return &CoordinatorRandomWordsFulfilled{ + RequestId: randomWordsFulfilledEvent.RequestId, + OutputSeed: randomWordsFulfilledEvent.OutputSeed, + Payment: randomWordsFulfilledEvent.Payment, + Success: randomWordsFulfilledEvent.Success, + Raw: randomWordsFulfilledEvent.Raw, + }, nil } } } @@ -632,7 +661,7 @@ func (v *EthereumVRFCoordinatorV2) WaitForSubscriptionConsumerRemoved(subID []ui } } -func (v *EthereumVRFCoordinatorV2) WaitForConfigSetEvent(timeout time.Duration) (*vrf_coordinator_v2.VRFCoordinatorV2ConfigSet, error) { +func (v *EthereumVRFCoordinatorV2) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) { eventsChannel := make(chan *vrf_coordinator_v2.VRFCoordinatorV2ConfigSet) subscription, err := v.coordinator.WatchConfigSet(nil, eventsChannel) if err != nil { @@ -647,7 +676,24 @@ func (v *EthereumVRFCoordinatorV2) WaitForConfigSetEvent(timeout time.Duration) case <-time.After(timeout): return nil, fmt.Errorf("timeout waiting for ConfigSet event") case event := <-eventsChannel: - return event, nil + return &CoordinatorConfigSet{ + MinimumRequestConfirmations: event.MinimumRequestConfirmations, + MaxGasLimit: event.MaxGasLimit, + StalenessSeconds: event.StalenessSeconds, + GasAfterPaymentCalculation: event.GasAfterPaymentCalculation, + FallbackWeiPerUnitLink: event.FallbackWeiPerUnitLink, + FeeConfig: VRFCoordinatorV2FeeConfig{ + FulfillmentFlatFeeLinkPPMTier1: event.FeeConfig.FulfillmentFlatFeeLinkPPMTier1, + FulfillmentFlatFeeLinkPPMTier2: event.FeeConfig.FulfillmentFlatFeeLinkPPMTier2, + FulfillmentFlatFeeLinkPPMTier3: event.FeeConfig.FulfillmentFlatFeeLinkPPMTier3, + FulfillmentFlatFeeLinkPPMTier4: event.FeeConfig.FulfillmentFlatFeeLinkPPMTier4, + FulfillmentFlatFeeLinkPPMTier5: event.FeeConfig.FulfillmentFlatFeeLinkPPMTier5, + ReqsForTier2: event.FeeConfig.ReqsForTier2, + ReqsForTier3: event.FeeConfig.ReqsForTier3, + ReqsForTier4: event.FeeConfig.ReqsForTier4, + ReqsForTier5: event.FeeConfig.ReqsForTier5, + }, + }, nil } } } @@ -794,14 +840,14 @@ func (v *EthereumVRFv2LoadTestConsumer) Address() string { } func (v *EthereumVRFv2LoadTestConsumer) RequestRandomness( - coordinator VRFCoordinatorV2, + coordinator Coordinator, keyHash [32]byte, subID uint64, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16, -) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) { +) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -810,23 +856,15 @@ func (v *EthereumVRFv2LoadTestConsumer) RequestRandomness( if err != nil { return nil, fmt.Errorf("RequestRandomWords failed, err: %w", err) } - err = v.client.ProcessTransaction(tx) - if err != nil { - return nil, fmt.Errorf("ProcessTransaction failed, err: %w", err) - } - err = v.client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("WaitForEvents failed, err: %w", err) - } - receipt, err := v.client.GetTxReceipt(tx.Hash()) + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) if err != nil { - return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err) + return nil, err } - randomWordsRequestedEvent, err := parseRequestRandomnessLogs(coordinator, receipt.Logs) - return randomWordsRequestedEvent, err + return randomWordsRequestedEvent, nil } func (v *EthereumVRFv2LoadTestConsumer) RequestRandomWordsWithForceFulfill( + coordinator Coordinator, keyHash [32]byte, requestConfirmations uint16, callbackGasLimit uint32, @@ -834,7 +872,7 @@ func (v *EthereumVRFv2LoadTestConsumer) RequestRandomWordsWithForceFulfill( requestCount uint16, subTopUpAmount *big.Int, linkAddress common.Address, -) (*types.Transaction, error) { +) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -849,10 +887,14 @@ func (v *EthereumVRFv2LoadTestConsumer) RequestRandomWordsWithForceFulfill( subTopUpAmount, linkAddress, ) + if err != nil { + return nil, fmt.Errorf("RequestRandomWords failed, err: %w", err) + } + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) if err != nil { return nil, err } - return tx, v.client.ProcessTransaction(tx) + return randomWordsRequestedEvent, nil } func (v *EthereumVRFv2Consumer) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrf_v2_consumer_wrapper.GetRequestStatus, error) { @@ -990,7 +1032,7 @@ func (v *EthereumVRFV2WrapperLoadTestConsumer) Fund(ethAmount *big.Float) error return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) } -func (v *EthereumVRFV2WrapperLoadTestConsumer) RequestRandomness(coordinator VRFCoordinatorV2, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) { +func (v *EthereumVRFV2WrapperLoadTestConsumer) RequestRandomness(coordinator Coordinator, requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -999,23 +1041,11 @@ func (v *EthereumVRFV2WrapperLoadTestConsumer) RequestRandomness(coordinator VRF if err != nil { return nil, err } - err = v.client.ProcessTransaction(tx) + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) if err != nil { return nil, err } - err = v.client.WaitForEvents() - if err != nil { - return nil, fmt.Errorf("WaitForEvents failed, err: %w", err) - } - receipt, err := v.client.GetTxReceipt(tx.Hash()) - if err != nil { - return nil, fmt.Errorf("GetTxReceipt failed, err: %w", err) - } - randomWordsRequestedEvent, err := parseRequestRandomnessLogs(coordinator, receipt.Logs) - if err != nil { - return nil, err - } - return randomWordsRequestedEvent, err + return randomWordsRequestedEvent, nil } func (v *EthereumVRFV2WrapperLoadTestConsumer) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrfv2_wrapper_load_test_consumer.GetRequestStatus, error) { @@ -1199,19 +1229,3 @@ func (v *EthereumVRFMockETHLINKFeed) SetBlockTimestampDeduction(blockTimestampDe } return v.client.ProcessTransaction(tx) } - -func parseRequestRandomnessLogs(coordinator VRFCoordinatorV2, logs []*types.Log) (*vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested, error) { - var randomWordsRequestedEvent *vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested - var err error - for _, eventLog := range logs { - for _, topic := range eventLog.Topics { - if topic.Cmp(vrf_coordinator_v2.VRFCoordinatorV2RandomWordsRequested{}.Topic()) == 0 { - randomWordsRequestedEvent, err = coordinator.ParseRandomWordsRequested(*eventLog) - if err != nil { - return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) - } - } - } - } - return randomWordsRequestedEvent, nil -} diff --git a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go index 432f700fa04..1c2bbcd0113 100644 --- a/integration-tests/contracts/ethereum_vrfv2plus_contracts.go +++ b/integration-tests/contracts/ethereum_vrfv2plus_contracts.go @@ -165,16 +165,42 @@ func (v *EthereumVRFCoordinatorV2_5) PendingRequestsExist(ctx context.Context, s return pendingRequestExists, nil } -func (v *EthereumVRFCoordinatorV2_5) GetSubscription(ctx context.Context, subID *big.Int) (vrf_coordinator_v2_5.GetSubscription, error) { +func (v *EthereumVRFCoordinatorV2_5) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) { + randomWordsRequested, err := v.coordinator.ParseRandomWordsRequested(log) + if err != nil { + return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) + } + coordinatorRandomWordsRequested := &CoordinatorRandomWordsRequested{ + KeyHash: randomWordsRequested.KeyHash, + RequestId: randomWordsRequested.RequestId, + PreSeed: randomWordsRequested.PreSeed, + SubId: randomWordsRequested.SubId.String(), + MinimumRequestConfirmations: randomWordsRequested.MinimumRequestConfirmations, + CallbackGasLimit: randomWordsRequested.CallbackGasLimit, + NumWords: randomWordsRequested.NumWords, + ExtraArgs: randomWordsRequested.ExtraArgs, + Sender: randomWordsRequested.Sender, + Raw: randomWordsRequested.Raw, + } + return coordinatorRandomWordsRequested, nil +} + +func (v *EthereumVRFCoordinatorV2_5) GetSubscription(ctx context.Context, subID *big.Int) (Subscription, error) { opts := &bind.CallOpts{ From: common.HexToAddress(v.client.GetDefaultWallet().Address()), Context: ctx, } subscription, err := v.coordinator.GetSubscription(opts, subID) if err != nil { - return vrf_coordinator_v2_5.GetSubscription{}, err + return Subscription{}, err } - return subscription, nil + return Subscription{ + Balance: subscription.Balance, + NativeBalance: subscription.NativeBalance, + SubOwner: subscription.SubOwner, + Consumers: subscription.Consumers, + ReqCount: subscription.ReqCount, + }, nil } func (v *EthereumVRFCoordinatorV2_5) GetLinkTotalBalance(ctx context.Context) (*big.Int, error) { @@ -455,9 +481,9 @@ func (v *EthereumVRFCoordinatorV2_5) WaitForSubscriptionCanceledEvent(subID *big } } -func (v *EthereumVRFCoordinatorV2_5) WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled, error) { +func (v *EthereumVRFCoordinatorV2_5) WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) { randomWordsFulfilledEventsChannel := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsFulfilled) - subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, requestID, subID) + subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, filter.RequestIds, filter.SubIDs) if err != nil { return nil, err } @@ -467,30 +493,48 @@ func (v *EthereumVRFCoordinatorV2_5) WaitForRandomWordsFulfilledEvent(subID []*b select { case err := <-subscription.Err(): return nil, err - case <-time.After(timeout): + case <-time.After(filter.Timeout): return nil, fmt.Errorf("timeout waiting for RandomWordsFulfilled event") case randomWordsFulfilledEvent := <-randomWordsFulfilledEventsChannel: - return randomWordsFulfilledEvent, nil + return &CoordinatorRandomWordsFulfilled{ + RequestId: randomWordsFulfilledEvent.RequestId, + OutputSeed: randomWordsFulfilledEvent.OutputSeed, + SubId: randomWordsFulfilledEvent.SubId.String(), + Payment: randomWordsFulfilledEvent.Payment, + NativePayment: randomWordsFulfilledEvent.NativePayment, + Success: randomWordsFulfilledEvent.Success, + OnlyPremium: randomWordsFulfilledEvent.OnlyPremium, + Raw: randomWordsFulfilledEvent.Raw, + }, nil } } } -func (v *EthereumVRFCoordinatorV2_5) WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested, error) { - randomWordsFulfilledEventsChannel := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25RandomWordsRequested) - subscription, err := v.coordinator.WatchRandomWordsRequested(nil, randomWordsFulfilledEventsChannel, keyHash, subID, sender) +func (v *EthereumVRFCoordinatorV2_5) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) { + eventsChannel := make(chan *vrf_coordinator_v2_5.VRFCoordinatorV25ConfigSet) + subscription, err := v.coordinator.WatchConfigSet(nil, eventsChannel) if err != nil { return nil, err } defer subscription.Unsubscribe() - for { select { case err := <-subscription.Err(): return nil, err case <-time.After(timeout): - return nil, fmt.Errorf("timeout waiting for RandomWordsRequested event") - case randomWordsFulfilledEvent := <-randomWordsFulfilledEventsChannel: - return randomWordsFulfilledEvent, nil + return nil, fmt.Errorf("timeout waiting for ConfigSet event") + case event := <-eventsChannel: + return &CoordinatorConfigSet{ + MinimumRequestConfirmations: event.MinimumRequestConfirmations, + MaxGasLimit: event.MaxGasLimit, + StalenessSeconds: event.StalenessSeconds, + GasAfterPaymentCalculation: event.GasAfterPaymentCalculation, + FallbackWeiPerUnitLink: event.FallbackWeiPerUnitLink, + FulfillmentFlatFeeNativePPM: event.FulfillmentFlatFeeNativePPM, + FulfillmentFlatFeeLinkDiscountPPM: event.FulfillmentFlatFeeLinkDiscountPPM, + NativePremiumPercentage: event.NativePremiumPercentage, + LinkPremiumPercentage: event.LinkPremiumPercentage, + }, nil } } } @@ -518,7 +562,15 @@ func (v *EthereumVRFCoordinatorV2_5) WaitForMigrationCompletedEvent(timeout time func (v *EthereumVRFv2PlusLoadTestConsumer) Address() string { return v.address.Hex() } -func (v *EthereumVRFv2PlusLoadTestConsumer) RequestRandomness(keyHash [32]byte, subID *big.Int, requestConfirmations uint16, callbackGasLimit uint32, nativePayment bool, numWords uint32, requestCount uint16) (*types.Transaction, error) { +func (v *EthereumVRFv2PlusLoadTestConsumer) RequestRandomness( + coordinator Coordinator, + keyHash [32]byte, subID *big.Int, + requestConfirmations uint16, + callbackGasLimit uint32, + nativePayment bool, + numWords uint32, + requestCount uint16, +) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -527,8 +579,11 @@ func (v *EthereumVRFv2PlusLoadTestConsumer) RequestRandomness(keyHash [32]byte, if err != nil { return nil, err } - - return tx, v.client.ProcessTransaction(tx) + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) + if err != nil { + return nil, err + } + return randomWordsRequestedEvent, nil } func (v *EthereumVRFv2PlusLoadTestConsumer) ResetMetrics() error { @@ -734,7 +789,8 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) SetConfig( fulfillmentFlatFeeNativePPM uint32, fulfillmentFlatFeeLinkDiscountPPM uint32, nativePremiumPercentage uint8, - linkPremiumPercentage uint8) error { + linkPremiumPercentage uint8, +) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err @@ -775,12 +831,13 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) SetLINKAndLINKNativeFeed(l func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) RegisterProvingKey( publicProvingKey [2]*big.Int, + gasLaneMaxGas uint64, ) error { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return err } - tx, err := v.coordinator.RegisterProvingKey(opts, publicProvingKey) + tx, err := v.coordinator.RegisterProvingKey(opts, publicProvingKey, gasLaneMaxGas) if err != nil { return err } @@ -895,9 +952,9 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) FindSubscriptionID() (*big return subscriptionIterator.Event.SubId, nil } -func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForRandomWordsFulfilledEvent(subID []*big.Int, requestID []*big.Int, timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled, error) { +func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForRandomWordsFulfilledEvent(filter RandomWordsFulfilledEventFilter) (*CoordinatorRandomWordsFulfilled, error) { randomWordsFulfilledEventsChannel := make(chan *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsFulfilled) - subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, requestID, subID) + subscription, err := v.coordinator.WatchRandomWordsFulfilled(nil, randomWordsFulfilledEventsChannel, filter.RequestIds, filter.SubIDs) if err != nil { return nil, err } @@ -907,10 +964,19 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForRandomWordsFulfille select { case err := <-subscription.Err(): return nil, err - case <-time.After(timeout): + case <-time.After(filter.Timeout): return nil, fmt.Errorf("timeout waiting for RandomWordsFulfilled event") case randomWordsFulfilledEvent := <-randomWordsFulfilledEventsChannel: - return randomWordsFulfilledEvent, nil + return &CoordinatorRandomWordsFulfilled{ + RequestId: randomWordsFulfilledEvent.RequestId, + OutputSeed: randomWordsFulfilledEvent.OutputSeed, + SubId: randomWordsFulfilledEvent.SubId.String(), + Payment: randomWordsFulfilledEvent.Payment, + NativePayment: randomWordsFulfilledEvent.NativePayment, + Success: randomWordsFulfilledEvent.Success, + OnlyPremium: randomWordsFulfilledEvent.OnlyPremium, + Raw: randomWordsFulfilledEvent.Raw, + }, nil } } } @@ -919,7 +985,7 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForMigrationCompletedE eventsChannel := make(chan *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionMigrationCompleted) subscription, err := v.coordinator.WatchMigrationCompleted(nil, eventsChannel) if err != nil { - return nil, err + return nil, fmt.Errorf("parse RandomWordsRequested log failed, err: %w", err) } defer subscription.Unsubscribe() @@ -935,22 +1001,51 @@ func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForMigrationCompletedE } } -func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForRandomWordsRequestedEvent(keyHash [][32]byte, subID []*big.Int, sender []common.Address, timeout time.Duration) (*vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested, error) { - eventsChannel := make(chan *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionRandomWordsRequested) - subscription, err := v.coordinator.WatchRandomWordsRequested(nil, eventsChannel, keyHash, subID, sender) +func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) ParseRandomWordsRequested(log types.Log) (*CoordinatorRandomWordsRequested, error) { + randomWordsRequested, err := v.coordinator.ParseRandomWordsRequested(log) if err != nil { return nil, err } - defer subscription.Unsubscribe() + coordinatorRandomWordsRequested := &CoordinatorRandomWordsRequested{ + KeyHash: randomWordsRequested.KeyHash, + RequestId: randomWordsRequested.RequestId, + PreSeed: randomWordsRequested.PreSeed, + SubId: randomWordsRequested.SubId.String(), + MinimumRequestConfirmations: randomWordsRequested.MinimumRequestConfirmations, + CallbackGasLimit: randomWordsRequested.CallbackGasLimit, + NumWords: randomWordsRequested.NumWords, + ExtraArgs: randomWordsRequested.ExtraArgs, + Sender: randomWordsRequested.Sender, + Raw: randomWordsRequested.Raw, + } + return coordinatorRandomWordsRequested, nil +} +func (v *EthereumVRFCoordinatorV2PlusUpgradedVersion) WaitForConfigSetEvent(timeout time.Duration) (*CoordinatorConfigSet, error) { + eventsChannel := make(chan *vrf_v2plus_upgraded_version.VRFCoordinatorV2PlusUpgradedVersionConfigSet) + subscription, err := v.coordinator.WatchConfigSet(nil, eventsChannel) + if err != nil { + return nil, err + } + defer subscription.Unsubscribe() for { select { case err := <-subscription.Err(): return nil, err case <-time.After(timeout): - return nil, fmt.Errorf("timeout waiting for RandomWordsRequested event") - case randomWordsRequestedEvent := <-eventsChannel: - return randomWordsRequestedEvent, nil + return nil, fmt.Errorf("timeout waiting for ConfigSet event") + case event := <-eventsChannel: + return &CoordinatorConfigSet{ + MinimumRequestConfirmations: event.MinimumRequestConfirmations, + MaxGasLimit: event.MaxGasLimit, + StalenessSeconds: event.StalenessSeconds, + GasAfterPaymentCalculation: event.GasAfterPaymentCalculation, + FallbackWeiPerUnitLink: event.FallbackWeiPerUnitLink, + FulfillmentFlatFeeNativePPM: event.FulfillmentFlatFeeNativePPM, + FulfillmentFlatFeeLinkDiscountPPM: event.FulfillmentFlatFeeLinkDiscountPPM, + NativePremiumPercentage: event.NativePremiumPercentage, + LinkPremiumPercentage: event.LinkPremiumPercentage, + }, nil } } } @@ -1020,7 +1115,13 @@ func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) Fund(ethAmount *big.Float) er return v.client.Fund(v.address.Hex(), ethAmount, gasEstimates) } -func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomness(requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*types.Transaction, error) { +func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomness( + coordinator Coordinator, + requestConfirmations uint16, + callbackGasLimit uint32, + numWords uint32, + requestCount uint16, +) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -1029,11 +1130,20 @@ func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomness(requestConf if err != nil { return nil, err } - - return tx, v.client.ProcessTransaction(tx) + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) + if err != nil { + return nil, err + } + return randomWordsRequestedEvent, nil } -func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomnessNative(requestConfirmations uint16, callbackGasLimit uint32, numWords uint32, requestCount uint16) (*types.Transaction, error) { +func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomnessNative( + coordinator Coordinator, + requestConfirmations uint16, + callbackGasLimit uint32, + numWords uint32, + requestCount uint16, +) (*CoordinatorRandomWordsRequested, error) { opts, err := v.client.TransactionOpts(v.client.GetDefaultWallet()) if err != nil { return nil, err @@ -1042,8 +1152,11 @@ func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) RequestRandomnessNative(reque if err != nil { return nil, err } - - return tx, v.client.ProcessTransaction(tx) + randomWordsRequestedEvent, err := RetrieveRequestRandomnessLogs(coordinator, v.client, tx) + if err != nil { + return nil, err + } + return randomWordsRequestedEvent, nil } func (v *EthereumVRFV2PlusWrapperLoadTestConsumer) GetRequestStatus(ctx context.Context, requestID *big.Int) (vrfv2plus_wrapper_load_test_consumer.GetRequestStatus, error) { diff --git a/integration-tests/load/vrfv2/vrfv2_test.go b/integration-tests/load/vrfv2/vrfv2_test.go index b27395769db..e420d66ec8c 100644 --- a/integration-tests/load/vrfv2/vrfv2_test.go +++ b/integration-tests/load/vrfv2/vrfv2_test.go @@ -2,6 +2,7 @@ package loadvrfv2 import ( "math/big" + "strconv" "sync" "testing" "time" @@ -119,7 +120,7 @@ func TestVRFV2Performance(t *testing.T) { for _, subID := range subIDs { subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %d", subID) - vrfv2.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) } subIDsForCancellingAfterTest = subIDs l.Debug().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") @@ -267,7 +268,7 @@ func TestVRFV2BHSPerformance(t *testing.T) { for _, subID := range underfundedSubIDs { subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %d", subID) - vrfv2.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subID, 10), vrfContracts.CoordinatorV2) } subIDsForCancellingAfterTest = underfundedSubIDs l.Debug().Int("Number of Subs", len(underfundedSubIDs)).Msg("Subs involved in the test") diff --git a/integration-tests/load/vrfv2plus/gun.go b/integration-tests/load/vrfv2plus/gun.go index 8be30afd412..8a99392fa57 100644 --- a/integration-tests/load/vrfv2plus/gun.go +++ b/integration-tests/load/vrfv2plus/gun.go @@ -44,7 +44,7 @@ func (m *BHSTestGun) Call(_ *wasp.Generator) *wasp.Response { if err != nil { return &wasp.Response{Error: err.Error(), Failed: true} } - _, err = vrfv2plus.RequestRandomnessAndWaitForRequestedEvent( + _, err = vrfv2plus.RequestRandomness( //the same consumer is used for all requests and in all subs m.contracts.VRFV2PlusConsumer[0], m.contracts.CoordinatorV2Plus, diff --git a/integration-tests/load/vrfv2plus/vrfv2plus_test.go b/integration-tests/load/vrfv2plus/vrfv2plus_test.go index bb9c33f43a6..d461b4cde20 100644 --- a/integration-tests/load/vrfv2plus/vrfv2plus_test.go +++ b/integration-tests/load/vrfv2plus/vrfv2plus_test.go @@ -118,7 +118,7 @@ func TestVRFV2PlusPerformance(t *testing.T) { for _, subID := range subIDs { subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %s", subID.String()) - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) } subIDsForCancellingAfterTest = subIDs l.Info().Int("Number of Subs", len(subIDs)).Msg("Subs involved in the test") @@ -268,7 +268,7 @@ func TestVRFV2PlusBHSPerformance(t *testing.T) { for _, subID := range underfundedSubIDs { subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information for subscription %s", subID.String()) - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) } subIDsForCancellingAfterTest = underfundedSubIDs l.Debug().Int("Number of Subs", len(underfundedSubIDs)).Msg("Subs involved in the test") diff --git a/integration-tests/smoke/vrfv2_test.go b/integration-tests/smoke/vrfv2_test.go index a834d1be757..be29ba45182 100644 --- a/integration-tests/smoke/vrfv2_test.go +++ b/integration-tests/smoke/vrfv2_test.go @@ -3,6 +3,7 @@ package smoke import ( "fmt" "math/big" + "strconv" "strings" "sync" "testing" @@ -24,6 +25,7 @@ import ( vrfcommon "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/common" "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2" "github.com/smartcontractkit/chainlink/integration-tests/client" + "github.com/smartcontractkit/chainlink/integration-tests/contracts" "github.com/smartcontractkit/chainlink/integration-tests/docker/test_env" tc "github.com/smartcontractkit/chainlink/integration-tests/testconfig" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" @@ -96,7 +98,7 @@ func TestVRFv2Basic(t *testing.T) { subIDForRequestRandomness := subIDsForRequestRandomness[0] subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscription, subIDForRequestRandomness, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForRequestRandomness, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForRequestRandomness...) subBalanceBeforeRequest := subscription.Balance @@ -152,7 +154,7 @@ func TestVRFv2Basic(t *testing.T) { subIDForJobRuns := subIDsForJobRuns[0] subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForJobRuns) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscription, subIDForJobRuns, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForJobRuns, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForJobRuns...) jobRunsBeforeTest, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.MustReadRunsByJob(nodeTypeToNodeMap[vrfcommon.VRF].Job.Data.ID) @@ -276,7 +278,7 @@ func TestVRFv2Basic(t *testing.T) { subIDForOracleWithdraw := subIDsForOracleWithDraw[0] subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForOracleWithdraw) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscription, subIDForOracleWithdraw, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForOracleWithdraw, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForOracleWithDraw...) fulfilledEventLink, err := vrfv2.RequestRandomnessAndWaitForFulfillment( @@ -337,7 +339,7 @@ func TestVRFv2Basic(t *testing.T) { subIDForCancelling := subIDsForCancelling[0] subscription, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForCancelling) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscription, subIDForCancelling, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscription, strconv.FormatUint(subIDForCancelling, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForCancelling...) testWalletAddress, err := actions.GenerateWallet() @@ -423,7 +425,7 @@ func TestVRFv2Basic(t *testing.T) { subIDForOwnerCancelling := subIDsForOwnerCancelling[0] subscriptionForCancelling, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForOwnerCancelling) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscriptionForCancelling, subIDForOwnerCancelling, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscriptionForCancelling, strconv.FormatUint(subIDForOwnerCancelling, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForOwnerCancelling...) // No GetActiveSubscriptionIds function available - skipping check @@ -590,7 +592,7 @@ func TestVRFv2MultipleSendingKeys(t *testing.T) { subIDForMultipleSendingKeys := subIDsForMultipleSendingKeys[0] subscriptionForMultipleSendingKeys, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForMultipleSendingKeys) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscriptionForMultipleSendingKeys, subIDForMultipleSendingKeys, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscriptionForMultipleSendingKeys, strconv.FormatUint(subIDForMultipleSendingKeys, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForMultipleSendingKeys...) txKeys, _, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTxKeys("evm") @@ -698,7 +700,7 @@ func TestVRFOwner(t *testing.T) { subIDForForceFulfill := subIDsForForceFulfill[0] subscriptionForMultipleSendingKeys, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForForceFulfill) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscriptionForMultipleSendingKeys, subIDForForceFulfill, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscriptionForMultipleSendingKeys, strconv.FormatUint(subIDForForceFulfill, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForForceFulfill...) vrfCoordinatorOwner, err := vrfContracts.CoordinatorV2.GetOwner(testcontext.Get(t)) @@ -850,7 +852,7 @@ func TestVRFV2WithBHS(t *testing.T) { subIDForBHS := subIDsForBHS[0] subscriptionForBHS, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForBHS) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscriptionForBHS, subIDForBHS, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscriptionForBHS, strconv.FormatUint(subIDForBHS, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForBHS...) randomWordsRequestedEvent, err := vrfv2.RequestRandomness( @@ -867,7 +869,7 @@ func TestVRFV2WithBHS(t *testing.T) { ) require.NoError(t, err, "error requesting randomness") - vrfv2.LogRandomnessRequestedEvent(l, vrfContracts.CoordinatorV2, randomWordsRequestedEvent) + vrfcommon.LogRandomnessRequestedEvent(l, vrfContracts.CoordinatorV2, randomWordsRequestedEvent, false) randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber var wg sync.WaitGroup wg.Add(1) @@ -878,11 +880,13 @@ func TestVRFV2WithBHS(t *testing.T) { err = vrfv2.FundSubscriptions(testEnv, chainID, big.NewFloat(*configCopy.VRFv2.General.SubscriptionFundingAmountLink), vrfContracts.LinkToken, vrfContracts.CoordinatorV2, subIDsForBHS) require.NoError(t, err, "error funding subscriptions") randomWordsFulfilledEvent, err := vrfContracts.CoordinatorV2.WaitForRandomWordsFulfilledEvent( - []*big.Int{randomWordsRequestedEvent.RequestId}, - time.Second*30, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + Timeout: configCopy.VRFv2.General.RandomWordsFulfilledEventTimeout.Duration, + }, ) require.NoError(t, err, "error waiting for randomness fulfilled event") - vrfv2.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2, randomWordsFulfilledEvent) + vrfcommon.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2, randomWordsFulfilledEvent, false) status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) @@ -909,7 +913,7 @@ func TestVRFV2WithBHS(t *testing.T) { subIDForBHS := subIDsForBHS[0] subscriptionForBHS, err := vrfContracts.CoordinatorV2.GetSubscription(testcontext.Get(t), subIDForBHS) require.NoError(t, err, "error getting subscription information") - vrfv2.LogSubDetails(l, subscriptionForBHS, subIDForBHS, vrfContracts.CoordinatorV2) + vrfcommon.LogSubDetails(l, subscriptionForBHS, strconv.FormatUint(subIDForBHS, 10), vrfContracts.CoordinatorV2) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForBHS...) randomWordsRequestedEvent, err := vrfv2.RequestRandomness( diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 2f58c2d0003..20871a12b77 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -23,6 +23,7 @@ import ( "github.com/smartcontractkit/chainlink/integration-tests/actions/vrf/vrfv2plus" "github.com/smartcontractkit/chainlink/integration-tests/client" "github.com/smartcontractkit/chainlink/integration-tests/contracts" + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/assets" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/blockhash_store" "github.com/smartcontractkit/chainlink/integration-tests/actions" @@ -99,7 +100,7 @@ func TestVRFv2Plus(t *testing.T) { subIDForRequestRandomness := subIDsForRequestRandomness[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subIDForRequestRandomness) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subIDForRequestRandomness, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subIDForRequestRandomness.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDsForRequestRandomness...) subBalanceBeforeRequest := subscription.Balance @@ -163,7 +164,7 @@ func TestVRFv2Plus(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) subNativeTokenBalanceBeforeRequest := subscription.NativeBalance @@ -262,7 +263,7 @@ func TestVRFv2Plus(t *testing.T) { //todo: uncomment when VRF-651 will be fixed //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") - vrfv2plus.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) + vrfcommon.LogFulfillmentDetailsLinkBilling(l, wrapperConsumerJuelsBalanceBeforeRequest, wrapperConsumerJuelsBalanceAfterRequest, consumerStatus, randomWordsFulfilledEvent) require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { @@ -311,7 +312,7 @@ func TestVRFv2Plus(t *testing.T) { //todo: uncomment when VRF-651 will be fixed //require.Equal(t, 1, consumerStatus.Paid.Cmp(randomWordsFulfilledEvent.Payment), "Expected Consumer contract pay more than the Coordinator Sub") - vrfv2plus.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) + vrfcommon.LogFulfillmentDetailsNativeBilling(l, wrapperConsumerBalanceBeforeRequestWei, wrapperConsumerBalanceAfterRequestWei, consumerStatus, randomWordsFulfilledEvent) require.Equal(t, *testConfig.NumberOfWords, uint32(len(consumerStatus.RandomWords))) for _, w := range consumerStatus.RandomWords { @@ -336,7 +337,7 @@ func TestVRFv2Plus(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) testWalletAddress, err := actions.GenerateWallet() @@ -444,7 +445,7 @@ func TestVRFv2Plus(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) activeSubscriptionIdsBeforeSubCancellation, err := vrfContracts.CoordinatorV2Plus.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0)) require.NoError(t, err) @@ -593,7 +594,7 @@ func TestVRFv2Plus(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) fulfilledEventLink, err := vrfv2plus.RequestRandomnessAndWaitForFulfillment( @@ -730,7 +731,7 @@ func TestVRFv2PlusMultipleSendingKeys(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) txKeys, _, err := nodeTypeToNodeMap[vrfcommon.VRF].CLNode.API.ReadTxKeys("evm") @@ -839,7 +840,7 @@ func TestVRFv2PlusMigration(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) activeSubIdsOldCoordinatorBeforeMigration, err := vrfContracts.CoordinatorV2Plus.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0)) @@ -857,7 +858,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = evmClient.WaitForEvents() require.NoError(t, err, vrfcommon.ErrWaitTXsComplete) - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -921,7 +922,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = evmClient.WaitForEvents() require.NoError(t, err, vrfcommon.ErrWaitTXsComplete) - vrfv2plus.LogMigrationCompletedEvent(l, migrationCompletedEvent, vrfContracts) + vrfv2plus.LogMigrationCompletedEvent(l, migrationCompletedEvent, vrfContracts.CoordinatorV2Plus) oldCoordinatorLinkTotalBalanceAfterMigration, oldCoordinatorEthTotalBalanceAfterMigration, err := vrfv2plus.GetCoordinatorTotalBalance(vrfContracts.CoordinatorV2Plus) require.NoError(t, err) @@ -976,7 +977,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.Equal(t, 0, expectedEthTotalBalanceForOldCoordinator.Cmp(oldCoordinatorEthTotalBalanceAfterMigration)) //Verify rand requests fulfills with Link Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillmentUpgraded( + _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[0], newCoordinator, vrfKey, @@ -988,7 +989,7 @@ func TestVRFv2PlusMigration(t *testing.T) { require.NoError(t, err, "error requesting randomness and waiting for fulfilment") //Verify rand requests fulfills with Native Token billing - _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillmentUpgraded( + _, err = vrfv2plus.RequestRandomnessAndWaitForFulfillment( consumers[1], newCoordinator, vrfKey, @@ -1023,7 +1024,7 @@ func TestVRFv2PlusMigration(t *testing.T) { subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) activeSubIdsOldCoordinatorBeforeMigration, err := vrfContracts.CoordinatorV2Plus.GetActiveSubscriptionIds(testcontext.Get(t), big.NewInt(0), big.NewInt(0)) require.NoError(t, err, "error occurred getting active sub ids") @@ -1041,7 +1042,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = evmClient.WaitForEvents() require.NoError(t, err, vrfcommon.ErrWaitTXsComplete) - _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator) + _, err = vrfv2plus.VRFV2PlusUpgradedVersionRegisterProvingKey(vrfKey.VRFKey, newCoordinator, uint64(assets.GWei(*configCopy.VRFv2Plus.General.CLNodeMaxGasPriceGWei).Int64())) require.NoError(t, err, fmt.Errorf("%s, err: %w", vrfcommon.ErrRegisteringProvingKey, err)) err = newCoordinator.SetConfig( @@ -1106,7 +1107,7 @@ func TestVRFv2PlusMigration(t *testing.T) { err = evmClient.WaitForEvents() require.NoError(t, err, vrfcommon.ErrWaitTXsComplete) - vrfv2plus.LogMigrationCompletedEvent(l, migrationCompletedEvent, vrfContracts) + vrfv2plus.LogMigrationCompletedEvent(l, migrationCompletedEvent, vrfContracts.CoordinatorV2Plus) oldCoordinatorLinkTotalBalanceAfterMigration, oldCoordinatorEthTotalBalanceAfterMigration, err := vrfv2plus.GetCoordinatorTotalBalance(vrfContracts.CoordinatorV2Plus) require.NoError(t, err) @@ -1160,7 +1161,7 @@ func TestVRFv2PlusMigration(t *testing.T) { // Verify rand requests fulfills with Link Token billing isNativeBilling := false - randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillmentUpgraded( + randomWordsFulfilledEvent, err := vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment( wrapperContracts.LoadTestConsumers[0], newCoordinator, vrfKey, @@ -1176,7 +1177,7 @@ func TestVRFv2PlusMigration(t *testing.T) { // Verify rand requests fulfills with Native Token billing isNativeBilling = true - randomWordsFulfilledEvent, err = vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillmentUpgraded( + randomWordsFulfilledEvent, err = vrfv2plus.DirectFundingRequestRandomnessAndWaitForFulfillment( wrapperContracts.LoadTestConsumers[0], newCoordinator, vrfKey, @@ -1269,28 +1270,20 @@ func TestVRFV2PlusWithBHS(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - _, err = consumers[0].RequestRandomness( - vrfKey.KeyHash, + randomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, subID, - *configCopy.VRFv2Plus.General.MinimumConfirmations, - *configCopy.VRFv2Plus.General.CallbackGasLimit, isNativeBilling, - *configCopy.VRFv2Plus.General.NumberOfWords, - *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + configCopy.VRFv2Plus.General, + l, ) require.NoError(t, err, "error requesting randomness") - randomWordsRequestedEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKey.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumers[0].Address())}, - time.Minute*1, - ) - require.NoError(t, err, "error waiting for randomness requested event") - vrfv2plus.LogRandomnessRequestedEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsRequestedEvent, isNativeBilling) randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber var wg sync.WaitGroup wg.Add(1) @@ -1309,12 +1302,14 @@ func TestVRFV2PlusWithBHS(t *testing.T) { ) require.NoError(t, err, "error funding subscriptions") randomWordsFulfilledEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( - []*big.Int{subID}, - []*big.Int{randomWordsRequestedEvent.RequestId}, - time.Second*30, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + SubIDs: []*big.Int{subID}, + Timeout: configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + }, ) require.NoError(t, err, "error waiting for randomness fulfilled event") - vrfv2plus.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsFulfilledEvent, isNativeBilling) + vrfcommon.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsFulfilledEvent, isNativeBilling) status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) @@ -1350,29 +1345,20 @@ func TestVRFV2PlusWithBHS(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) //BHS node should fill in blockhashes into BHS contract depending on the waitBlocks and lookBackBlocks settings - _, err = consumers[0].RequestRandomness( - vrfKey.KeyHash, + randomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, subID, - *configCopy.VRFv2Plus.General.MinimumConfirmations, - *configCopy.VRFv2Plus.General.CallbackGasLimit, isNativeBilling, - *configCopy.VRFv2Plus.General.NumberOfWords, - *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + configCopy.VRFv2Plus.General, + l, ) require.NoError(t, err, "error requesting randomness") - - randomWordsRequestedEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKey.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumers[0].Address())}, - time.Minute*1, - ) - require.NoError(t, err, "error waiting for randomness requested event") - vrfv2plus.LogRandomnessRequestedEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsRequestedEvent, isNativeBilling) randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber _, err = vrfContracts.BHS.GetBlockHash(testcontext.Get(t), big.NewInt(int64(randRequestBlockNumber))) require.Error(t, err, "error not occurred when getting blockhash for a blocknumber which was not stored in BHS contract") @@ -1507,28 +1493,20 @@ func TestVRFV2PlusWithBHF(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) - _, err = consumers[0].RequestRandomness( - vrfKey.KeyHash, + randomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( + consumers[0], + vrfContracts.CoordinatorV2Plus, + vrfKey, subID, - *configCopy.VRFv2Plus.General.MinimumConfirmations, - *configCopy.VRFv2Plus.General.CallbackGasLimit, isNativeBilling, - *configCopy.VRFv2Plus.General.NumberOfWords, - *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + configCopy.VRFv2Plus.General, + l, ) require.NoError(t, err, "error requesting randomness") - randomWordsRequestedEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsRequestedEvent( - [][32]byte{vrfKey.KeyHash}, - []*big.Int{subID}, - []common.Address{common.HexToAddress(consumers[0].Address())}, - time.Minute*1, - ) - require.NoError(t, err, "error waiting for randomness requested event") - vrfv2plus.LogRandomnessRequestedEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsRequestedEvent, isNativeBilling) randRequestBlockNumber := randomWordsRequestedEvent.Raw.BlockNumber var wg sync.WaitGroup wg.Add(1) @@ -1550,12 +1528,14 @@ func TestVRFV2PlusWithBHF(t *testing.T) { ) require.NoError(t, err, "error funding subscriptions") randomWordsFulfilledEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( - []*big.Int{subID}, - []*big.Int{randomWordsRequestedEvent.RequestId}, - time.Minute*2, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{randomWordsRequestedEvent.RequestId}, + SubIDs: []*big.Int{subID}, + Timeout: configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + }, ) require.NoError(t, err, "error waiting for randomness fulfilled event") - vrfv2plus.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsFulfilledEvent, isNativeBilling) + vrfcommon.LogRandomWordsFulfilledEvent(l, vrfContracts.CoordinatorV2Plus, randomWordsFulfilledEvent, isNativeBilling) status, err := consumers[0].GetRequestStatus(testcontext.Get(t), randomWordsFulfilledEvent.RequestId) require.NoError(t, err, "error getting rand request status") require.True(t, status.Fulfilled) @@ -1656,11 +1636,11 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) // 2. create request but without fulfilment - e.g. simulation failure (insufficient balance in the sub, ) - initialReqRandomWordsRequestedEvent, err := vrfv2plus.RequestRandomnessAndWaitForRequestedEvent( + initialReqRandomWordsRequestedEvent, err := vrfv2plus.RequestRandomness( consumers[0], vrfContracts.CoordinatorV2Plus, vrfKey, @@ -1761,9 +1741,11 @@ func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { Str("subID", subID.String()). Msg("Waiting for initalReqRandomWordsFulfilledEvent") initalReqRandomWordsFulfilledEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( - []*big.Int{subID}, - []*big.Int{initialReqRandomWordsRequestedEvent.RequestId}, - configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + contracts.RandomWordsFulfilledEventFilter{ + RequestIds: []*big.Int{initialReqRandomWordsRequestedEvent.RequestId}, + SubIDs: []*big.Int{subID}, + Timeout: configCopy.VRFv2Plus.General.RandomWordsFulfilledEventTimeout.Duration, + }, ) require.NoError(t, err, "error waiting for initial request RandomWordsFulfilledEvent") @@ -1847,7 +1829,7 @@ func TestVRFv2PlusPendingBlockSimulationAndZeroConfirmationDelays(t *testing.T) subID := subIDs[0] subscription, err := vrfContracts.CoordinatorV2Plus.GetSubscription(testcontext.Get(t), subID) require.NoError(t, err, "error getting subscription information") - vrfv2plus.LogSubDetails(l, subscription, subID, vrfContracts.CoordinatorV2Plus) + vrfcommon.LogSubDetails(l, subscription, subID.String(), vrfContracts.CoordinatorV2Plus) subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) var isNativeBilling = true From e52951f613bb7b58bff4ae6fc2a5ed082e9ac420 Mon Sep 17 00:00:00 2001 From: Bartek Tofel Date: Fri, 19 Apr 2024 12:52:33 +0200 Subject: [PATCH 16/26] [TT-1073] use Seth with health check (#12889) * use latest Seth * use latest Seth with optional RPC health check --- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- integration-tests/testconfig/default.toml | 4 ++++ 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 2917be8d1fc..7a09fa9875b 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -29,7 +29,7 @@ require ( github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 - github.com/smartcontractkit/seth v0.1.5 + github.com/smartcontractkit/seth v0.1.6 github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.0 github.com/stretchr/testify v1.9.0 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 7611301476b..5b689d0ae3d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1541,8 +1541,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 h1:1WFjrrVrWoQ9UpVMh7Mx4jDpzhmo1h8hFUKd9awIhIU= github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= -github.com/smartcontractkit/seth v0.1.5 h1:tobdA3uzRHubN/ytE6bSq1dtvmaXjKdaHEGW5Re9I1U= -github.com/smartcontractkit/seth v0.1.5/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= +github.com/smartcontractkit/seth v0.1.6 h1:exU96KiKM/gxvp7OR8KkOXnTgbtFNepdhMBvyobFKCw= +github.com/smartcontractkit/seth v0.1.6/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 08b3e13b646..b77ad247c01 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -21,7 +21,7 @@ require ( github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 - github.com/smartcontractkit/seth v0.1.5 + github.com/smartcontractkit/seth v0.1.6 github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 github.com/smartcontractkit/wasp v0.4.6 github.com/stretchr/testify v1.9.0 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 4bc1c163799..8926c81f74d 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1526,8 +1526,8 @@ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJ github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 h1:1WFjrrVrWoQ9UpVMh7Mx4jDpzhmo1h8hFUKd9awIhIU= github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= -github.com/smartcontractkit/seth v0.1.5 h1:tobdA3uzRHubN/ytE6bSq1dtvmaXjKdaHEGW5Re9I1U= -github.com/smartcontractkit/seth v0.1.5/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= +github.com/smartcontractkit/seth v0.1.6 h1:exU96KiKM/gxvp7OR8KkOXnTgbtFNepdhMBvyobFKCw= +github.com/smartcontractkit/seth v0.1.6/go.mod h1:2TMOZQ8WTAw7rR1YBbXpnad6VmT/+xDd/nXLmB7Eero= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1/go.mod h1:q6f4fe39oZPdsh1i57WznEZgxd8siidMaSFq3wdPmVg= github.com/smartcontractkit/tdh2/go/tdh2 v0.0.0-20230906073235-9e478e5e19f1 h1:Dai1bn+Q5cpeGMQwRdjOdVjG8mmFFROVkSKuUgBErRQ= diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index a277c22b4c2..ef3f60d4282 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -43,6 +43,10 @@ ephemeral_addresses_number = 0 # That's because the one we are about to send would get queued, possibly for a very long time pending_nonce_protection_enabled = false +# when enabled when creating a new Seth client we will send 10k wei from root address to root address +# to make sure transaction can be submited and mined +check_rpc_health_on_start = false + [Seth.nonce_manager] key_sync_rate_limit_per_sec = 10 key_sync_timeout = "2s" From 63abd08cd55b6dc31e74c6d3e50597eb8400eeb4 Mon Sep 17 00:00:00 2001 From: Bolek <1416262+bolekk@users.noreply.github.com> Date: Fri, 19 Apr 2024 03:56:26 -0700 Subject: [PATCH 17/26] [KS-79] Remote trigger setup (#12845) 1. Fully set up a (hardcoded) capability DON in Syncer and move fake Mercury producer over there. 2. Refactor remote Aggregator interface to reduce marshaling steps. 3. Avoid redundant calls to RegisterTrigger. 4. Minor change to Prometheus config in Peer Wrapper. --- .changeset/orange-squids-kick.md | 5 + core/capabilities/remote/trigger_publisher.go | 24 ++- .../capabilities/remote/trigger_subscriber.go | 15 +- core/capabilities/remote/types/types.go | 3 +- core/capabilities/remote/utils.go | 25 +++- core/capabilities/remote/utils_test.go | 40 ++--- core/capabilities/syncer.go | 141 ++++++++++++++---- core/capabilities/syncer_test.go | 2 +- core/scripts/go.mod | 3 +- core/scripts/go.sum | 4 +- core/services/p2p/wrapper/wrapper.go | 4 +- core/services/workflows/delegate.go | 57 ------- go.mod | 2 +- go.sum | 4 +- integration-tests/go.mod | 3 +- integration-tests/go.sum | 4 +- integration-tests/load/go.mod | 3 +- integration-tests/load/go.sum | 4 +- 18 files changed, 199 insertions(+), 144 deletions(-) create mode 100644 .changeset/orange-squids-kick.md diff --git a/.changeset/orange-squids-kick.md b/.changeset/orange-squids-kick.md new file mode 100644 index 00000000000..a934e70063d --- /dev/null +++ b/.changeset/orange-squids-kick.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#internal Remote Trigger setup diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index 94ca58e6156..fac01fdead6 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -5,6 +5,7 @@ import ( sync "sync" "time" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -87,17 +88,21 @@ func (p *triggerPublisher) Receive(msg *types.MessageBody) { key := registrationKey{msg.CallerDonId, req.Metadata.WorkflowID} nowMs := time.Now().UnixMilli() p.mu.Lock() + defer p.mu.Unlock() p.messageCache.Insert(key, sender, nowMs, msg.Payload) + _, exists := p.registrations[key] + if exists { + p.lggr.Debugw("trigger registration already exists", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID) + return + } // NOTE: require 2F+1 by default, introduce different strategies later (KS-76) minRequired := uint32(2*callerDon.F + 1) ready, payloads := p.messageCache.Ready(key, minRequired, nowMs-int64(p.config.RegistrationExpiryMs), false) - p.mu.Unlock() if !ready { p.lggr.Debugw("not ready to aggregate yet", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "minRequired", minRequired) return } - agg := NewDefaultModeAggregator(uint32(callerDon.F + 1)) - aggregated, err := agg.Aggregate("", payloads) + aggregated, err := AggregateModeRaw(payloads, uint32(callerDon.F+1)) if err != nil { p.lggr.Errorw("failed to aggregate trigger registrations", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "err", err) return @@ -107,7 +112,6 @@ func (p *triggerPublisher) Receive(msg *types.MessageBody) { p.lggr.Errorw("failed to unmarshal request", "capabilityId", p.capInfo.ID, "err", err) return } - p.mu.Lock() callbackCh := make(chan commoncap.CapabilityResponse) ctx, cancel := p.stopCh.NewCtx() err = p.underlying.RegisterTrigger(ctx, callbackCh, unmarshaled) @@ -123,7 +127,6 @@ func (p *triggerPublisher) Receive(msg *types.MessageBody) { } else { p.lggr.Errorw("failed to register trigger", "capabilityId", p.capInfo.ID, "workflowId", req.Metadata.WorkflowID, "err", err) } - p.mu.Unlock() } else { p.lggr.Errorw("received trigger request with unknown method", "method", msg.Method, "sender", sender) } @@ -171,7 +174,13 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh chan commoncap.Capability p.lggr.Infow("triggerEventLoop channel closed", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId) return } - p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId) + triggerEvent := capabilities.TriggerEvent{} + err := response.Value.UnwrapTo(&triggerEvent) + if err != nil { + p.lggr.Errorw("can't unwrap trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "err", err) + break + } + p.lggr.Debugw("received trigger event", "capabilityId", p.capInfo.ID, "workflowId", key.workflowId, "triggerEventID", triggerEvent.ID) marshaled, err := pb.MarshalCapabilityResponse(response) if err != nil { p.lggr.Debugw("can't marshal trigger event", "err", err) @@ -186,7 +195,8 @@ func (p *triggerPublisher) triggerEventLoop(callbackCh chan commoncap.Capability Metadata: &types.MessageBody_TriggerEventMetadata{ TriggerEventMetadata: &types.TriggerEventMetadata{ // NOTE: optionally introduce batching across workflows as an optimization - WorkflowIds: []string{key.workflowId}, + WorkflowIds: []string{key.workflowId}, + TriggerEventId: triggerEvent.ID, }, }, } diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index 2c893d2b86e..4b46935eab6 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -102,6 +102,7 @@ func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, callback chan<- callback: callback, rawRequest: rawRequest, } + s.lggr.Infow("RegisterTrigger called", "capabilityId", s.capInfo.ID, "donId", s.capDonInfo.ID, "workflowID", request.Metadata.WorkflowID) return nil } @@ -114,8 +115,8 @@ func (s *triggerSubscriber) registrationLoop() { case <-s.stopCh: return case <-ticker.C: - s.lggr.Infow("register trigger for remote capability", "capabilityId", s.capInfo.ID, "donId", s.capDonInfo.ID, "nMembers", len(s.capDonInfo.Members)) s.mu.RLock() + s.lggr.Infow("register trigger for remote capability", "capabilityId", s.capInfo.ID, "donId", s.capDonInfo.ID, "nMembers", len(s.capDonInfo.Members), "nWorkflows", len(s.registeredWorkflows)) for _, registration := range s.registeredWorkflows { // NOTE: send to all by default, introduce different strategies later (KS-76) for _, peerID := range s.capDonInfo.Members { @@ -180,18 +181,14 @@ func (s *triggerSubscriber) Receive(msg *types.MessageBody) { continue } if ready { + s.lggr.Debugw("trigger event ready to aggregate", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) aggregatedResponse, err := s.aggregator.Aggregate(meta.TriggerEventId, payloads) if err != nil { - s.lggr.Errorw("failed to aggregate responses", "capabilityId", s.capInfo.ID, "workflowId", workflowId, "err", err) + s.lggr.Errorw("failed to aggregate responses", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId, "err", err) continue } - unmarshaled, err := pb.UnmarshalCapabilityResponse(aggregatedResponse) - if err != nil { - s.lggr.Errorw("failed to unmarshal responses", "capabilityId", s.capInfo.ID, "workflowId", workflowId, "err", err) - continue - } - s.lggr.Info("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) - registration.callback <- unmarshaled + s.lggr.Infow("remote trigger event aggregated", "triggerEventID", meta.TriggerEventId, "capabilityId", s.capInfo.ID, "workflowId", workflowId) + registration.callback <- aggregatedResponse } } } else { diff --git a/core/capabilities/remote/types/types.go b/core/capabilities/remote/types/types.go index 327c2b8d4c5..d8307d09f80 100644 --- a/core/capabilities/remote/types/types.go +++ b/core/capabilities/remote/types/types.go @@ -1,6 +1,7 @@ package types import ( + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -23,7 +24,7 @@ type Receiver interface { } type Aggregator interface { - Aggregate(eventID string, responses [][]byte) ([]byte, error) + Aggregate(eventID string, responses [][]byte) (commoncap.CapabilityResponse, error) } // NOTE: this type will become part of the Registry (KS-108) diff --git a/core/capabilities/remote/utils.go b/core/capabilities/remote/utils.go index 92c5e5447a5..dba24b843cc 100644 --- a/core/capabilities/remote/utils.go +++ b/core/capabilities/remote/utils.go @@ -10,6 +10,8 @@ import ( "google.golang.org/protobuf/proto" + commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/pb" remotetypes "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote/types" p2ptypes "github.com/smartcontractkit/chainlink/v2/core/services/p2p/types" ) @@ -60,16 +62,29 @@ func NewDefaultModeAggregator(minIdenticalResponses uint32) *defaultModeAggregat } } -func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) ([]byte, error) { +func (a *defaultModeAggregator) Aggregate(_ string, responses [][]byte) (commoncap.CapabilityResponse, error) { + found, err := AggregateModeRaw(responses, a.minIdenticalResponses) + if err != nil { + return commoncap.CapabilityResponse{}, fmt.Errorf("failed to aggregate responses, err: %w", err) + } + + unmarshaled, err := pb.UnmarshalCapabilityResponse(found) + if err != nil { + return commoncap.CapabilityResponse{}, fmt.Errorf("failed to unmarshal aggregated responses, err: %w", err) + } + return unmarshaled, nil +} + +func AggregateModeRaw(elemList [][]byte, minIdenticalResponses uint32) ([]byte, error) { hashToCount := make(map[string]uint32) var found []byte - for _, resp := range responses { + for _, elem := range elemList { hasher := sha256.New() - hasher.Write(resp) + hasher.Write(elem) sha := hex.EncodeToString(hasher.Sum(nil)) hashToCount[sha]++ - if hashToCount[sha] >= a.minIdenticalResponses { - found = resp + if hashToCount[sha] >= minIdenticalResponses { + found = elem break } } diff --git a/core/capabilities/remote/utils_test.go b/core/capabilities/remote/utils_test.go index 120cf5604ca..b5f97af99ed 100644 --- a/core/capabilities/remote/utils_test.go +++ b/core/capabilities/remote/utils_test.go @@ -1,7 +1,6 @@ package remote_test import ( - "bytes" "crypto/ed25519" "crypto/rand" "testing" @@ -90,29 +89,32 @@ func TestToPeerID(t *testing.T) { } func TestDefaultModeAggregator_Aggregate(t *testing.T) { - capResponse1 := marshalCapabilityResponse(t, triggerEvent1, nil) - capResponse2 := marshalCapabilityResponse(t, triggerEvent2, nil) + val, err := values.Wrap(triggerEvent1) + require.NoError(t, err) + capResponse1 := commoncap.CapabilityResponse{ + Value: val, + Err: nil, + } + marshaled1, err := pb.MarshalCapabilityResponse(capResponse1) + require.NoError(t, err) + + val2, err := values.Wrap(triggerEvent2) + require.NoError(t, err) + capResponse2 := commoncap.CapabilityResponse{ + Value: val2, + Err: nil, + } + marshaled2, err := pb.MarshalCapabilityResponse(capResponse2) + require.NoError(t, err) agg := remote.NewDefaultModeAggregator(2) - _, err := agg.Aggregate("", [][]byte{capResponse1}) + _, err = agg.Aggregate("", [][]byte{marshaled1}) require.Error(t, err) - _, err = agg.Aggregate("", [][]byte{capResponse1, capResponse2}) + _, err = agg.Aggregate("", [][]byte{marshaled1, marshaled2}) require.Error(t, err) - res, err := agg.Aggregate("", [][]byte{capResponse1, capResponse2, capResponse1}) - require.NoError(t, err) - require.True(t, bytes.Equal(res, capResponse1)) -} - -func marshalCapabilityResponse(t *testing.T, capValue any, capError error) []byte { - val, err := values.Wrap(capValue) - require.NoError(t, err) - capResponse := commoncap.CapabilityResponse{ - Value: val, - Err: capError, - } - marshaled, err := pb.MarshalCapabilityResponse(capResponse) + res, err := agg.Aggregate("", [][]byte{marshaled1, marshaled2, marshaled1}) require.NoError(t, err) - return marshaled + require.Equal(t, res, capResponse1) } diff --git a/core/capabilities/syncer.go b/core/capabilities/syncer.go index 748910c462b..2de917b5f9f 100644 --- a/core/capabilities/syncer.go +++ b/core/capabilities/syncer.go @@ -3,8 +3,12 @@ package capabilities import ( "context" "slices" + "sync" + "time" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/mercury" + "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" "github.com/smartcontractkit/chainlink-common/pkg/services" "github.com/smartcontractkit/chainlink-common/pkg/types" @@ -32,12 +36,12 @@ var defaultStreamConfig = p2ptypes.StreamConfig{ OutgoingMessageBufferSize: 1000000, MaxMessageLenBytes: 100000, MessageRateLimiter: ragep2p.TokenBucketParams{ - Rate: 10.0, + Rate: 100.0, Capacity: 1000, }, BytesRateLimiter: ragep2p.TokenBucketParams{ - Rate: 10.0, - Capacity: 1000, + Rate: 100000.0, + Capacity: 1000000, }, } @@ -54,14 +58,16 @@ func NewRegistrySyncer(peerWrapper p2ptypes.PeerWrapper, registry types.Capabili func (s *registrySyncer) Start(ctx context.Context) error { // NOTE: temporary hard-coded DONs workflowDONPeers := []string{ - "12D3KooWF3dVeJ6YoT5HFnYhmwQWWMoEwVFzJQ5kKCMX3ZityxMC", - "12D3KooWQsmok6aD8PZqt3RnJhQRrNzKHLficq7zYFRp7kZ1hHP8", - "12D3KooWJbZLiMuGeKw78s3LM5TNgBTJHcF39DraxLu14bucG9RN", - "12D3KooWGqfSPhHKmQycfhRjgUDE2vg9YWZN27Eue8idb2ZUk6EH", + "12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N", + "12D3KooWG1AyvwmCpZ93J8pBQUE1SuzrjDXnT4BeouncHR3jWLCG", + "12D3KooWGeUKZBRMbx27FUTgBwZa9Ap9Ym92mywwpuqkEtz8XWyv", + "12D3KooW9zYWQv3STmDeNDidyzxsJSTxoCTLicafgfeEz9nhwhC4", } - capabilityDONPeers := []string{ - "12D3KooWHCcyTPmYFB1ydNvNcXw5WyAomRzGSFu1B7hpB4yi8Smf", - "12D3KooWPv6eqJvYz7TcQWk4Y4XjZ1uQ7mUKahdDXj65ht95zH6a", + triggerDONPeers := []string{ + "12D3KooWJrthXtnPHw7xyHFAxo6NxifYTvc8igKYaA6wRRRqtsMb", + "12D3KooWFQekP9sGex4XhqEJav5EScjTpDVtDqJFg1JvrePBCEGJ", + "12D3KooWFLEq4hYtdyKWwe47dXGEbSiHMZhmr5xLSJNhpfiEz8NF", + "12D3KooWN2hztiXNNS1jMQTTvvPRYcarK1C7T3Mdqk4x4gwyo5WS", } allPeers := make(map[ragetypes.PeerID]p2ptypes.StreamConfig) addPeersToDONInfo := func(peers []string, donInfo *remotetypes.DON) error { @@ -76,12 +82,12 @@ func (s *registrySyncer) Start(ctx context.Context) error { } return nil } - workflowDonInfo := remotetypes.DON{ID: "workflowDon1"} + workflowDonInfo := remotetypes.DON{ID: "workflowDon1", F: 1} if err := addPeersToDONInfo(workflowDONPeers, &workflowDonInfo); err != nil { return err } - capabilityDonInfo := remotetypes.DON{ID: "capabilityDon1"} - if err := addPeersToDONInfo(capabilityDONPeers, &capabilityDonInfo); err != nil { + triggerCapabilityDonInfo := remotetypes.DON{ID: "capabilityDon1", F: 1} + if err := addPeersToDONInfo(triggerDONPeers, &triggerCapabilityDonInfo); err != nil { return err } err := s.peerWrapper.GetPeer().UpdateConnections(allPeers) @@ -89,7 +95,7 @@ func (s *registrySyncer) Start(ctx context.Context) error { return err } // NOTE: temporary hard-coded capabilities - capId := "sample_remote_trigger" + capId := "mercury-trigger" triggerInfo := commoncap.CapabilityInfo{ ID: capId, CapabilityType: commoncap.CapabilityTypeTrigger, @@ -98,36 +104,42 @@ func (s *registrySyncer) Start(ctx context.Context) error { } myId := s.peerWrapper.GetPeer().ID().String() config := remotetypes.RemoteTriggerConfig{ - RegistrationRefreshMs: 20000, + RegistrationRefreshMs: 20000, + MinResponsesToAggregate: uint32(triggerCapabilityDonInfo.F) + 1, } if slices.Contains(workflowDONPeers, myId) { s.lggr.Info("member of a workflow DON - starting remote subscribers") - triggerCap := remote.NewTriggerSubscriber(config, triggerInfo, capabilityDonInfo, workflowDonInfo, s.dispatcher, nil, s.lggr) + aggregator := triggers.NewMercuryRemoteAggregator(s.lggr) + triggerCap := remote.NewTriggerSubscriber(config, triggerInfo, triggerCapabilityDonInfo, workflowDonInfo, s.dispatcher, aggregator, s.lggr) err = s.registry.Add(ctx, triggerCap) if err != nil { s.lggr.Errorw("failed to add remote target capability to registry", "error", err) return err } - err = s.dispatcher.SetReceiver(capId, capabilityDonInfo.ID, triggerCap) + err = s.dispatcher.SetReceiver(capId, triggerCapabilityDonInfo.ID, triggerCap) if err != nil { - s.lggr.Errorw("failed to set receiver", "capabilityId", capId, "donId", capabilityDonInfo.ID, "error", err) + s.lggr.Errorw("workflow DON failed to set receiver", "capabilityId", capId, "donId", triggerCapabilityDonInfo.ID, "error", err) return err } s.subServices = append(s.subServices, triggerCap) } - if slices.Contains(capabilityDONPeers, myId) { + if slices.Contains(triggerDONPeers, myId) { s.lggr.Info("member of a capability DON - starting remote publishers") workflowDONs := map[string]remotetypes.DON{ workflowDonInfo.ID: workflowDonInfo, } - underlying := &noOpTrigger{info: triggerInfo, lggr: s.lggr} - triggerCap := remote.NewTriggerPublisher(config, underlying, triggerInfo, capabilityDonInfo, workflowDONs, s.dispatcher, s.lggr) - err = s.dispatcher.SetReceiver(capId, capabilityDonInfo.ID, triggerCap) + underlying := triggers.NewMercuryTriggerService(1000, s.lggr) + triggerCap := remote.NewTriggerPublisher(config, underlying, triggerInfo, triggerCapabilityDonInfo, workflowDONs, s.dispatcher, s.lggr) + err = s.dispatcher.SetReceiver(capId, triggerCapabilityDonInfo.ID, triggerCap) if err != nil { - s.lggr.Errorw("failed to set receiver", "capabilityId", capId, "donId", capabilityDonInfo.ID, "error", err) + s.lggr.Errorw("capability DON failed to set receiver", "capabilityId", capId, "donId", triggerCapabilityDonInfo.ID, "error", err) return err } + s.subServices = append(s.subServices, underlying) s.subServices = append(s.subServices, triggerCap) + // NOTE: temporary mock Mercury data producer + mockMercuryDataProducer := NewMockMercuryDataProducer(underlying, s.lggr) + s.subServices = append(s.subServices, mockMercuryDataProducer) } // NOTE: temporary service start - should be managed by capability creation for _, srv := range s.subServices { @@ -163,21 +175,86 @@ func (s *registrySyncer) Name() string { return "RegistrySyncer" } -type noOpTrigger struct { - info commoncap.CapabilityInfo - lggr logger.Logger +type mockMercuryDataProducer struct { + trigger *triggers.MercuryTriggerService + wg sync.WaitGroup + closeCh chan struct{} + lggr logger.Logger } -func (t *noOpTrigger) Info(_ context.Context) (commoncap.CapabilityInfo, error) { - return t.info, nil +var _ services.Service = &mockMercuryDataProducer{} + +func NewMockMercuryDataProducer(trigger *triggers.MercuryTriggerService, lggr logger.Logger) *mockMercuryDataProducer { + return &mockMercuryDataProducer{ + trigger: trigger, + closeCh: make(chan struct{}), + lggr: lggr, + } } -func (t *noOpTrigger) RegisterTrigger(_ context.Context, _ chan<- commoncap.CapabilityResponse, request commoncap.CapabilityRequest) error { - t.lggr.Infow("no-op trigger RegisterTrigger", "workflowID", request.Metadata.WorkflowID) +func (m *mockMercuryDataProducer) Start(ctx context.Context) error { + m.wg.Add(1) + go m.loop() return nil } -func (t *noOpTrigger) UnregisterTrigger(_ context.Context, request commoncap.CapabilityRequest) error { - t.lggr.Infow("no-op trigger RegisterTrigger", "workflowID", request.Metadata.WorkflowID) +func (m *mockMercuryDataProducer) loop() { + defer m.wg.Done() + + sleepSec := 60 + ticker := time.NewTicker(time.Duration(sleepSec) * time.Second) + defer ticker.Stop() + + prices := []int64{300000, 40000, 5000000} + + for range ticker.C { + for i := range prices { + prices[i] = prices[i] + 1 + } + + reports := []mercury.FeedReport{ + { + FeedID: "0x1111111111111111111100000000000000000000000000000000000000000000", + FullReport: []byte{0x11, 0xaa, 0xbb, 0xcc}, + BenchmarkPrice: prices[0], + ObservationTimestamp: time.Now().Unix(), + }, + { + FeedID: "0x2222222222222222222200000000000000000000000000000000000000000000", + FullReport: []byte{0x22, 0xaa, 0xbb, 0xcc}, + BenchmarkPrice: prices[1], + ObservationTimestamp: time.Now().Unix(), + }, + { + FeedID: "0x3333333333333333333300000000000000000000000000000000000000000000", + FullReport: []byte{0x33, 0xaa, 0xbb, 0xcc}, + BenchmarkPrice: prices[2], + ObservationTimestamp: time.Now().Unix(), + }, + } + + m.lggr.Infow("New set of Mercury reports", "timestamp", time.Now().Unix(), "payload", reports) + err := m.trigger.ProcessReport(reports) + if err != nil { + m.lggr.Errorw("failed to process Mercury reports", "err", err, "timestamp", time.Now().Unix(), "payload", reports) + } + } +} + +func (m *mockMercuryDataProducer) Close() error { + close(m.closeCh) + m.wg.Wait() + return nil +} + +func (m *mockMercuryDataProducer) HealthReport() map[string]error { return nil } + +func (m *mockMercuryDataProducer) Ready() error { + return nil +} + +func (m *mockMercuryDataProducer) Name() string { + return "mockMercuryDataProducer" +} diff --git a/core/capabilities/syncer_test.go b/core/capabilities/syncer_test.go index 335b9774689..757135635d8 100644 --- a/core/capabilities/syncer_test.go +++ b/core/capabilities/syncer_test.go @@ -20,7 +20,7 @@ func TestSyncer_CleanStartClose(t *testing.T) { lggr := logger.TestLogger(t) ctx := testutils.Context(t) var pid ragetypes.PeerID - err := pid.UnmarshalText([]byte("12D3KooWF3dVeJ6YoT5HFnYhmwQWWMoEwVFzJQ5kKCMX3ZityxMC")) + err := pid.UnmarshalText([]byte("12D3KooWBCF1XT5Wi8FzfgNCqRL76Swv8TRU3TiD4QiJm8NMNX7N")) require.NoError(t, err) peer := mocks.NewPeer(t) peer.On("UpdateConnections", mock.Anything).Return(nil) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index afb3248f629..8c68d33c604 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 @@ -249,6 +249,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 449d8124317..2883ee68528 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,8 +1185,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb h1:yLDt5cQWRwcFM5VEdSTbc3vDrYrxYqBjSvyTMU/o8s4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb/go.mod h1:kstYjAGqBswdZpl7YkSPeXBDVwaY1VaR6tUMPWl8ykA= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/p2p/wrapper/wrapper.go b/core/services/p2p/wrapper/wrapper.go index fd47c6c2dd2..acb6694b5a3 100644 --- a/core/services/p2p/wrapper/wrapper.go +++ b/core/services/p2p/wrapper/wrapper.go @@ -66,7 +66,9 @@ func convertPeerConfig(keystoreP2P keystore.P2P, p2pConfig config.P2P) (p2p.Peer DeltaDial: p2pConfig.V2().DeltaDial().Duration(), DiscovererDatabase: discovererDB, - MetricsRegisterer: prometheus.DefaultRegisterer, + // NOTE: this is equivalent to prometheus.DefaultRegisterer, but we need to use a separate + // object to avoid conflicts with the OCR registerer + MetricsRegisterer: prometheus.NewRegistry(), } return peerConfig, nil diff --git a/core/services/workflows/delegate.go b/core/services/workflows/delegate.go index dedf53e369b..ed7d266131a 100644 --- a/core/services/workflows/delegate.go +++ b/core/services/workflows/delegate.go @@ -3,13 +3,10 @@ package workflows import ( "context" "fmt" - "time" "github.com/google/uuid" "github.com/pelletier/go-toml" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/mercury" - "github.com/smartcontractkit/chainlink-common/pkg/capabilities/triggers" "github.com/smartcontractkit/chainlink-common/pkg/types" "github.com/smartcontractkit/chainlink/v2/core/capabilities/targets" "github.com/smartcontractkit/chainlink/v2/core/chains/legacyevm" @@ -45,14 +42,6 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, spec job.Job) ([]job.Ser d.logger.Errorw("could not initialize writes", err) } - trigger := triggers.NewMercuryTriggerService(0, d.logger) - err = d.registry.Add(context.Background(), trigger) - if err != nil { - d.logger.Errorw("could not add mercury trigger to registry", err) - } else { - go mercuryEventLoop(trigger, d.logger) - } - cfg := Config{ Lggr: d.logger, Spec: spec.WorkflowSpec.Workflow, @@ -70,52 +59,6 @@ func NewDelegate(logger logger.Logger, registry types.CapabilitiesRegistry, lega return &Delegate{logger: logger, registry: registry, legacyEVMChains: legacyEVMChains} } -func mercuryEventLoop(trigger *triggers.MercuryTriggerService, logger logger.Logger) { - sleepSec := 60 * time.Second - ticker := time.NewTicker(sleepSec) - defer ticker.Stop() - - prices := []int64{300000, 2000, 5000000} - - for range ticker.C { - for i := range prices { - prices[i] = prices[i] + 1 - } - - t := time.Now().Round(sleepSec).Unix() - reports, err := emitReports(logger, trigger, t, prices) - if err != nil { - logger.Errorw("failed to process Mercury reports", "err", err, "timestamp", time.Now().Unix(), "payload", reports) - } - } -} - -func emitReports(logger logger.Logger, trigger *triggers.MercuryTriggerService, t int64, prices []int64) ([]mercury.FeedReport, error) { - reports := []mercury.FeedReport{ - { - FeedID: "0x1111111111111111111100000000000000000000000000000000000000000000", - FullReport: []byte(fmt.Sprintf(`{ "feed": "ETH", "price": %d }`, prices[0])), - BenchmarkPrice: prices[0], - ObservationTimestamp: t, - }, - { - FeedID: "0x2222222222222222222200000000000000000000000000000000000000000000", - FullReport: []byte(fmt.Sprintf(`{ "feed": "LINK", "price": %d }`, prices[1])), - BenchmarkPrice: prices[1], - ObservationTimestamp: t, - }, - { - FeedID: "0x3333333333333333333300000000000000000000000000000000000000000000", - FullReport: []byte(fmt.Sprintf(`{ "feed": "BTC", "price": %d }`, prices[2])), - BenchmarkPrice: prices[2], - ObservationTimestamp: t, - }, - } - - logger.Infow("New set of Mercury reports", "timestamp", time.Now().Unix(), "payload", reports) - return reports, trigger.ProcessReport(reports) -} - func ValidatedWorkflowSpec(tomlString string) (job.Job, error) { var jb = job.Job{ExternalJobID: uuid.New()} diff --git a/go.mod b/go.mod index 9ad9b8c6dbe..3970b20a4bf 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 diff --git a/go.sum b/go.sum index 6e041744bf2..753ffcda235 100644 --- a/go.sum +++ b/go.sum @@ -1180,8 +1180,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb h1:yLDt5cQWRwcFM5VEdSTbc3vDrYrxYqBjSvyTMU/o8s4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb/go.mod h1:kstYjAGqBswdZpl7YkSPeXBDVwaY1VaR6tUMPWl8ykA= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 7a09fa9875b..7746cca72d6 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -24,7 +24,7 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 github.com/smartcontractkit/chainlink-testing-framework v1.28.3 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 @@ -368,6 +368,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/russross/blackfriday v1.6.0 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/sercand/kuberesolver/v5 v5.1.1 // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 5b689d0ae3d..c18825a1f24 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1519,8 +1519,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb h1:yLDt5cQWRwcFM5VEdSTbc3vDrYrxYqBjSvyTMU/o8s4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb/go.mod h1:kstYjAGqBswdZpl7YkSPeXBDVwaY1VaR6tUMPWl8ykA= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index b77ad247c01..f0f62ce41e7 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 github.com/smartcontractkit/chainlink-testing-framework v1.28.3 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 @@ -355,6 +355,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 // indirect github.com/rogpeppe/go-internal v1.11.0 // indirect github.com/russross/blackfriday v1.6.0 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/scylladb/go-reflectx v1.0.1 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 8926c81f74d..13d80e3a8e1 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1502,8 +1502,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb h1:yLDt5cQWRwcFM5VEdSTbc3vDrYrxYqBjSvyTMU/o8s4= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240415164156-8872a8f311cb/go.mod h1:kstYjAGqBswdZpl7YkSPeXBDVwaY1VaR6tUMPWl8ykA= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From bfd9a8be64a3d24e2c527c08b27b1c30a3ee8ffc Mon Sep 17 00:00:00 2001 From: Tate Date: Fri, 19 Apr 2024 07:51:54 -0600 Subject: [PATCH 18/26] Make the golangci action take an id to separate the metrics (#12886) --- .github/actions/golangci-lint/action.yml | 5 ++++- .github/workflows/ci-core.yml | 1 + .github/workflows/ci-scripts.yml | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/actions/golangci-lint/action.yml b/.github/actions/golangci-lint/action.yml index 3542c865959..e52dd1aed7b 100644 --- a/.github/actions/golangci-lint/action.yml +++ b/.github/actions/golangci-lint/action.yml @@ -2,6 +2,9 @@ name: CI lint for Golang description: Runs CI lint for Golang inputs: # general inputs + id: + description: Unique metrics collection id + required: true name: description: Name of the lint action default: lint @@ -72,7 +75,7 @@ runs: if: always() uses: smartcontractkit/push-gha-metrics-action@dea9b546553cb4ca936607c2267a09c004e4ab3f # v3.0.0 with: - id: chainlink-golang-ci + id: chainlink-golang-ci-${{ inputs.id }} basic-auth: ${{ inputs.gc-basic-auth }} hostname: ${{ inputs.gc-host }} org-id: ${{ inputs.gc-org-id }} diff --git a/.github/workflows/ci-core.yml b/.github/workflows/ci-core.yml index 9d9ff595ed0..c97af329639 100644 --- a/.github/workflows/ci-core.yml +++ b/.github/workflows/ci-core.yml @@ -63,6 +63,7 @@ jobs: uses: ./.github/actions/golangci-lint if: ${{ needs.filter.outputs.changes == 'true' }} with: + id: core gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} diff --git a/.github/workflows/ci-scripts.yml b/.github/workflows/ci-scripts.yml index 78c26ff258e..814c354cfe6 100644 --- a/.github/workflows/ci-scripts.yml +++ b/.github/workflows/ci-scripts.yml @@ -13,6 +13,7 @@ jobs: - name: Golang Lint uses: ./.github/actions/golangci-lint with: + id: scripts name: lint-scripts go-directory: core/scripts go-version-file: core/scripts/go.mod From d90229e7a7011f8dc1c331dffb0ad1eeaddba46f Mon Sep 17 00:00:00 2001 From: Matthew Pendrey Date: Fri, 19 Apr 2024 15:24:35 +0100 Subject: [PATCH 19/26] Update core to be compatible with changes made in chainlink-common as part of KS-120 (moving capabilities to use streams) (#12857) * Update core to be compatible with changes made in chainlink-common as part of KS-120 * upgrade common version --- .changeset/fresh-lizards-love.md | 5 ++++ core/capabilities/registry_test.go | 6 ++--- core/capabilities/remote/target.go | 8 +++--- core/capabilities/remote/target_test.go | 6 +++-- core/capabilities/remote/trigger_publisher.go | 8 +++--- .../remote/trigger_publisher_test.go | 4 +-- .../capabilities/remote/trigger_subscriber.go | 19 ++++++++++---- .../remote/trigger_subscriber_test.go | 7 ++--- core/capabilities/targets/write_target.go | 26 +++++++++++-------- .../capabilities/targets/write_target_test.go | 8 ++---- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 +-- core/services/workflows/engine.go | 9 ++++++- core/services/workflows/engine_test.go | 18 ++++++++----- go.mod | 2 +- go.sum | 4 +-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 +-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 +-- 20 files changed, 88 insertions(+), 60 deletions(-) create mode 100644 .changeset/fresh-lizards-love.md diff --git a/.changeset/fresh-lizards-love.md b/.changeset/fresh-lizards-love.md new file mode 100644 index 00000000000..8e6e5d5cfef --- /dev/null +++ b/.changeset/fresh-lizards-love.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +#internal Updates required to work with chainlink-common changes to support grpc streams for capabilities diff --git a/core/capabilities/registry_test.go b/core/capabilities/registry_test.go index 3f8ca397495..3bed31a957a 100644 --- a/core/capabilities/registry_test.go +++ b/core/capabilities/registry_test.go @@ -19,8 +19,8 @@ type mockCapability struct { capabilities.CapabilityInfo } -func (m *mockCapability) Execute(ctx context.Context, callback chan<- capabilities.CapabilityResponse, req capabilities.CapabilityRequest) error { - return nil +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { + return nil, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { @@ -140,7 +140,7 @@ func TestRegistry_ChecksExecutionAPIByType(t *testing.T) { { name: "trigger", newCapability: func(ctx context.Context, reg *coreCapabilities.Registry) (string, error) { - odt := triggers.NewOnDemand() + odt := triggers.NewOnDemand(logger.TestLogger(t)) info, err := odt.Info(ctx) require.NoError(t, err) return info.ID, reg.Add(ctx, odt) diff --git a/core/capabilities/remote/target.go b/core/capabilities/remote/target.go index bacc06c0310..92b0724512a 100644 --- a/core/capabilities/remote/target.go +++ b/core/capabilities/remote/target.go @@ -50,7 +50,7 @@ func (c *remoteTargetCaller) UnregisterFromWorkflow(ctx context.Context, request return errors.New("not implemented") } -func (c *remoteTargetCaller) Execute(ctx context.Context, callback chan<- commoncap.CapabilityResponse, request commoncap.CapabilityRequest) error { +func (c *remoteTargetCaller) Execute(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { c.lggr.Debugw("not implemented - executing fake remote target capability", "capabilityId", c.capInfo.ID, "nMembers", len(c.donInfo.Members)) for _, peerID := range c.donInfo.Members { m := &types.MessageBody{ @@ -60,10 +60,12 @@ func (c *remoteTargetCaller) Execute(ctx context.Context, callback chan<- common } err := c.dispatcher.Send(peerID, m) if err != nil { - return err + return nil, err } } - return nil + + // TODO: return a channel that will be closed when all responses are received + return nil, nil } func (c *remoteTargetCaller) Receive(msg *types.MessageBody) { diff --git a/core/capabilities/remote/target_test.go b/core/capabilities/remote/target_test.go index 904cd5b9c71..a9e72d778df 100644 --- a/core/capabilities/remote/target_test.go +++ b/core/capabilities/remote/target_test.go @@ -3,8 +3,8 @@ package remote_test import ( "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/require" commoncap "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink/v2/core/capabilities/remote" @@ -24,5 +24,7 @@ func TestTarget_Placeholder(t *testing.T) { dispatcher := remoteMocks.NewDispatcher(t) dispatcher.On("Send", mock.Anything, mock.Anything).Return(nil) target := remote.NewRemoteTargetCaller(commoncap.CapabilityInfo{}, donInfo, dispatcher, lggr) - require.NoError(t, target.Execute(ctx, nil, commoncap.CapabilityRequest{})) + + _, err := target.Execute(ctx, commoncap.CapabilityRequest{}) + assert.NoError(t, err) } diff --git a/core/capabilities/remote/trigger_publisher.go b/core/capabilities/remote/trigger_publisher.go index fac01fdead6..d06254657c7 100644 --- a/core/capabilities/remote/trigger_publisher.go +++ b/core/capabilities/remote/trigger_publisher.go @@ -41,7 +41,7 @@ type registrationKey struct { } type pubRegState struct { - callback chan<- commoncap.CapabilityResponse + callback <-chan commoncap.CapabilityResponse request commoncap.CapabilityRequest } @@ -112,9 +112,8 @@ func (p *triggerPublisher) Receive(msg *types.MessageBody) { p.lggr.Errorw("failed to unmarshal request", "capabilityId", p.capInfo.ID, "err", err) return } - callbackCh := make(chan commoncap.CapabilityResponse) ctx, cancel := p.stopCh.NewCtx() - err = p.underlying.RegisterTrigger(ctx, callbackCh, unmarshaled) + callbackCh, err := p.underlying.RegisterTrigger(ctx, unmarshaled) cancel() if err == nil { p.registrations[key] = &pubRegState{ @@ -153,7 +152,6 @@ func (p *triggerPublisher) registrationCleanupLoop() { cancel() p.lggr.Infow("unregistered trigger", "capabilityId", p.capInfo.ID, "callerDonID", key.callerDonId, "workflowId", key.workflowId, "err", err) // after calling UnregisterTrigger, the underlying trigger will not send any more events to the channel - close(req.callback) delete(p.registrations, key) p.messageCache.Delete(key) } @@ -163,7 +161,7 @@ func (p *triggerPublisher) registrationCleanupLoop() { } } -func (p *triggerPublisher) triggerEventLoop(callbackCh chan commoncap.CapabilityResponse, key registrationKey) { +func (p *triggerPublisher) triggerEventLoop(callbackCh <-chan commoncap.CapabilityResponse, key registrationKey) { defer p.wg.Done() for { select { diff --git a/core/capabilities/remote/trigger_publisher_test.go b/core/capabilities/remote/trigger_publisher_test.go index 2a31646de5b..dd107e12e61 100644 --- a/core/capabilities/remote/trigger_publisher_test.go +++ b/core/capabilities/remote/trigger_publisher_test.go @@ -87,9 +87,9 @@ func (t *testTrigger) Info(_ context.Context) (commoncap.CapabilityInfo, error) return t.info, nil } -func (t *testTrigger) RegisterTrigger(_ context.Context, _ chan<- commoncap.CapabilityResponse, request commoncap.CapabilityRequest) error { +func (t *testTrigger) RegisterTrigger(_ context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { t.registrationsCh <- request - return nil + return nil, nil } func (t *testTrigger) UnregisterTrigger(_ context.Context, request commoncap.CapabilityRequest) error { diff --git a/core/capabilities/remote/trigger_subscriber.go b/core/capabilities/remote/trigger_subscriber.go index 4b46935eab6..a7cb58c008b 100644 --- a/core/capabilities/remote/trigger_subscriber.go +++ b/core/capabilities/remote/trigger_subscriber.go @@ -51,7 +51,11 @@ var _ commoncap.TriggerCapability = &triggerSubscriber{} var _ types.Receiver = &triggerSubscriber{} var _ services.Service = &triggerSubscriber{} -func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, localDonInfo types.DON, dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { +// TODO makes this configurable with a default +const defaultSendChannelBufferSize = 1000 + +func NewTriggerSubscriber(config types.RemoteTriggerConfig, capInfo commoncap.CapabilityInfo, capDonInfo types.DON, localDonInfo types.DON, + dispatcher types.Dispatcher, aggregator types.Aggregator, lggr logger.Logger) *triggerSubscriber { if aggregator == nil { lggr.Warnw("no aggregator provided, using default MODE aggregator", "capabilityId", capInfo.ID) aggregator = NewDefaultModeAggregator(uint32(capDonInfo.F + 1)) @@ -88,22 +92,25 @@ func (s *triggerSubscriber) Info(ctx context.Context) (commoncap.CapabilityInfo, return s.capInfo, nil } -func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, callback chan<- commoncap.CapabilityResponse, request commoncap.CapabilityRequest) error { +func (s *triggerSubscriber) RegisterTrigger(ctx context.Context, request commoncap.CapabilityRequest) (<-chan commoncap.CapabilityResponse, error) { rawRequest, err := pb.MarshalCapabilityRequest(request) if err != nil { - return err + return nil, err } if request.Metadata.WorkflowID == "" { - return errors.New("empty workflowID") + return nil, errors.New("empty workflowID") } s.mu.Lock() defer s.mu.Unlock() + + callback := make(chan commoncap.CapabilityResponse, defaultSendChannelBufferSize) s.registeredWorkflows[request.Metadata.WorkflowID] = &subRegState{ callback: callback, rawRequest: rawRequest, } + s.lggr.Infow("RegisterTrigger called", "capabilityId", s.capInfo.ID, "donId", s.capDonInfo.ID, "workflowID", request.Metadata.WorkflowID) - return nil + return callback, nil } func (s *triggerSubscriber) registrationLoop() { @@ -141,6 +148,8 @@ func (s *triggerSubscriber) registrationLoop() { func (s *triggerSubscriber) UnregisterTrigger(ctx context.Context, request commoncap.CapabilityRequest) error { s.mu.Lock() defer s.mu.Unlock() + + close(s.registeredWorkflows[request.Metadata.WorkflowID].callback) delete(s.registeredWorkflows, request.Metadata.WorkflowID) // Registrations will quickly expire on all remote nodes. // Alternatively, we could send UnregisterTrigger messages right away. diff --git a/core/capabilities/remote/trigger_subscriber_test.go b/core/capabilities/remote/trigger_subscriber_test.go index ce901169f10..df04306e2b0 100644 --- a/core/capabilities/remote/trigger_subscriber_test.go +++ b/core/capabilities/remote/trigger_subscriber_test.go @@ -67,12 +67,13 @@ func TestTriggerSubscriber_RegisterAndReceive(t *testing.T) { } subscriber := remote.NewTriggerSubscriber(config, capInfo, capDonInfo, workflowDonInfo, dispatcher, nil, lggr) require.NoError(t, subscriber.Start(ctx)) - triggerEventCallbackCh := make(chan commoncap.CapabilityResponse, 2) - require.NoError(t, subscriber.RegisterTrigger(ctx, triggerEventCallbackCh, commoncap.CapabilityRequest{ + + triggerEventCallbackCh, err := subscriber.RegisterTrigger(ctx, commoncap.CapabilityRequest{ Metadata: commoncap.RequestMetadata{ WorkflowID: workflowID1, }, - })) + }) + require.NoError(t, err) <-awaitRegistrationMessageCh // receive trigger event diff --git a/core/capabilities/targets/write_target.go b/core/capabilities/targets/write_target.go index 677b1148ebb..43b02939c04 100644 --- a/core/capabilities/targets/write_target.go +++ b/core/capabilities/targets/write_target.go @@ -28,7 +28,8 @@ import ( var forwardABI = evmtypes.MustGetABI(forwarder.KeystoneForwarderMetaData.ABI) -func InitializeWrite(registry commontypes.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, lggr logger.Logger) error { +func InitializeWrite(registry commontypes.CapabilitiesRegistry, legacyEVMChains legacyevm.LegacyChainContainer, + lggr logger.Logger) error { for _, chain := range legacyEVMChains.Slice() { capability := NewEvmWrite(chain, lggr) if err := registry.Add(context.TODO(), capability); err != nil { @@ -157,7 +158,7 @@ func encodePayload(args []any, rawSelector string) ([]byte, error) { // return append(method.ID, arguments...), nil } -func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.CapabilityResponse, request capabilities.CapabilityRequest) error { +func (cap *EvmWrite) Execute(ctx context.Context, request capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { cap.lggr.Debugw("Execute", "request", request) // TODO: idempotency @@ -168,22 +169,23 @@ func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.C reqConfig, err := parseConfig(request.Config) if err != nil { - return err + return nil, err } inputsAny, err := request.Inputs.Unwrap() if err != nil { - return err + return nil, err } inputs := inputsAny.(map[string]any) rep, ok := inputs["report"] if !ok { - return errors.New("malformed data: inputs doesn't contain a report key") + return nil, errors.New("malformed data: inputs doesn't contain a report key") } if rep == nil { // We received any empty report -- this means we should skip transmission. cap.lggr.Debugw("Skipping empty report", "request", request) + callback := make(chan capabilities.CapabilityResponse) go func() { // TODO: cast tx.Error to Err (or Value to Value?) callback <- capabilities.CapabilityResponse{ @@ -192,18 +194,18 @@ func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.C } close(callback) }() - return nil + return callback, nil } // evaluate any variables in reqConfig.Params args, err := evaluateParams(reqConfig.Params, inputs) if err != nil { - return err + return nil, err } data, err := encodePayload(args, reqConfig.ABI) if err != nil { - return err + return nil, err } // TODO: validate encoded report is prefixed with workflowID and executionID that match the request meta @@ -214,7 +216,7 @@ func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.C // construct forwarding payload calldata, err := forwardABI.Pack("report", common.HexToAddress(reqConfig.Address), data, signatures) if err != nil { - return err + return nil, err } txMeta := &txmgr.TxMeta{ @@ -238,9 +240,11 @@ func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.C } tx, err := txm.CreateTransaction(ctx, req) if err != nil { - return err + return nil, err } cap.lggr.Debugw("Transaction submitted", "request", request, "transaction", tx) + + callback := make(chan capabilities.CapabilityResponse) go func() { // TODO: cast tx.Error to Err (or Value to Value?) callback <- capabilities.CapabilityResponse{ @@ -249,7 +253,7 @@ func (cap *EvmWrite) Execute(ctx context.Context, callback chan<- capabilities.C } close(callback) }() - return nil + return callback, nil } func (cap *EvmWrite) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { diff --git a/core/capabilities/targets/write_target_test.go b/core/capabilities/targets/write_target_test.go index fd68234ca70..744fcd9d2e7 100644 --- a/core/capabilities/targets/write_target_test.go +++ b/core/capabilities/targets/write_target_test.go @@ -82,9 +82,7 @@ func TestEvmWrite(t *testing.T) { }) - ch := make(chan capabilities.CapabilityResponse) - - err = capability.Execute(ctx, ch, req) + ch, err := capability.Execute(ctx, req) require.NoError(t, err) response := <-ch @@ -134,9 +132,7 @@ func TestEvmWrite_EmptyReport(t *testing.T) { Inputs: inputs, } - ch := make(chan capabilities.CapabilityResponse) - - err = capability.Execute(ctx, ch, req) + ch, err := capability.Execute(ctx, req) require.NoError(t, err) response := <-ch diff --git a/core/scripts/go.mod b/core/scripts/go.mod index 8c68d33c604..c7cd3a72d75 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -21,7 +21,7 @@ require ( github.com/prometheus/client_golang v1.17.0 github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 2883ee68528..22bde9d5929 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1185,8 +1185,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index f6b8c63ed15..71d9ab9463e 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -183,10 +183,17 @@ func (e *Engine) registerTrigger(ctx context.Context, t *triggerCapability) erro Config: tc, Inputs: triggerInputs, } - err = t.trigger.RegisterTrigger(ctx, e.triggerEvents, triggerRegRequest) + eventsCh, err := t.trigger.RegisterTrigger(ctx, triggerRegRequest) if err != nil { return fmt.Errorf("failed to instantiate trigger %s, %s", t.Type, err) } + + go func() { + for event := range eventsCh { + e.triggerEvents <- event + } + }() + return nil } diff --git a/core/services/workflows/engine_test.go b/core/services/workflows/engine_test.go index edb924f9874..7bb6cd00c1c 100644 --- a/core/services/workflows/engine_test.go +++ b/core/services/workflows/engine_test.go @@ -79,16 +79,18 @@ func newMockCapability(info capabilities.CapabilityInfo, transform func(capabili } } -func (m *mockCapability) Execute(ctx context.Context, ch chan<- capabilities.CapabilityResponse, req capabilities.CapabilityRequest) error { +func (m *mockCapability) Execute(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { cr, err := m.transform(req) if err != nil { - return err + return nil, err } + ch := make(chan capabilities.CapabilityResponse, 10) + + m.response <- cr ch <- cr close(ch) - m.response <- cr - return nil + return ch, nil } func (m *mockCapability) RegisterToWorkflow(ctx context.Context, request capabilities.RegisterToWorkflowRequest) error { @@ -102,13 +104,14 @@ func (m *mockCapability) UnregisterFromWorkflow(ctx context.Context, request cap type mockTriggerCapability struct { capabilities.CapabilityInfo triggerEvent capabilities.CapabilityResponse + ch chan capabilities.CapabilityResponse } var _ capabilities.TriggerCapability = (*mockTriggerCapability)(nil) -func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, ch chan<- capabilities.CapabilityResponse, req capabilities.CapabilityRequest) error { - ch <- m.triggerEvent - return nil +func (m *mockTriggerCapability) RegisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) (<-chan capabilities.CapabilityResponse, error) { + m.ch <- m.triggerEvent + return m.ch, nil } func (m *mockTriggerCapability) UnregisterTrigger(ctx context.Context, req capabilities.CapabilityRequest) error { @@ -217,6 +220,7 @@ func mockTrigger(t *testing.T) (capabilities.TriggerCapability, capabilities.Cap "issues a trigger when a mercury report is received.", "v1.0.0", ), + ch: make(chan capabilities.CapabilityResponse, 10), } resp, err := values.NewMap(map[string]any{ "123": decimal.NewFromFloat(1.00), diff --git a/go.mod b/go.mod index 3970b20a4bf..c9695f0d98e 100644 --- a/go.mod +++ b/go.mod @@ -72,7 +72,7 @@ require ( github.com/shopspring/decimal v1.3.1 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 diff --git a/go.sum b/go.sum index 753ffcda235..b8a75291feb 100644 --- a/go.sum +++ b/go.sum @@ -1180,8 +1180,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 7746cca72d6..29da646554f 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -24,7 +24,7 @@ require ( github.com/segmentio/ksuid v1.0.4 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e github.com/smartcontractkit/chainlink-testing-framework v1.28.3 github.com/smartcontractkit/chainlink-vrf v0.0.0-20240222010609-cd67d123c772 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 diff --git a/integration-tests/go.sum b/integration-tests/go.sum index c18825a1f24..b650c96f43d 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1519,8 +1519,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index f0f62ce41e7..729642044cf 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -16,7 +16,7 @@ require ( github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.3 - github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 + github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e github.com/smartcontractkit/chainlink-testing-framework v1.28.3 github.com/smartcontractkit/chainlink/integration-tests v0.0.0-20240214231432-4ad5eb95178c github.com/smartcontractkit/chainlink/v2 v2.9.0-beta0.0.20240216210048-da02459ddad8 diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 13d80e3a8e1..5cd4c98c4a1 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1502,8 +1502,8 @@ github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCq github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfsE3+8OEzT3Q0Z9au0z1BPWs= github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0 h1:K7Y+gd0lEumrhgaIQFjC8reXadJOMVgDI4xsCAsiuSo= -github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419013737-4554767e4db0/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= +github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= From 7c059b2c26ed6d99a40403b4f690c0f3e08154b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deividas=20Kar=C5=BEinauskas?= Date: Fri, 19 Apr 2024 18:37:43 +0300 Subject: [PATCH 20/26] Add CapabilityRegistry skeleton (#12888) * Add CapabilityRegistry skeleton * Update storage var name * Generate wrappers and add changesets --- .changeset/plenty-wombats-grab.md | 5 + contracts/.changeset/old-pianos-trade.md | 5 + .../scripts/native_solc_compile_all_keystone | 1 + .../src/v0.8/keystone/CapabilityRegistry.sol | 41 + .../keystone/test/CapabilityRegistry.t.sol | 21 + .../keystone_capability_registry.go | 768 ++++++++++++++++++ ...rapper-dependency-versions-do-not-edit.txt | 1 + core/gethwrappers/keystone/go_generate.go | 1 + 8 files changed, 843 insertions(+) create mode 100644 .changeset/plenty-wombats-grab.md create mode 100644 contracts/.changeset/old-pianos-trade.md create mode 100644 contracts/src/v0.8/keystone/CapabilityRegistry.sol create mode 100644 contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol create mode 100644 core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go diff --git a/.changeset/plenty-wombats-grab.md b/.changeset/plenty-wombats-grab.md new file mode 100644 index 00000000000..84fb96f8b80 --- /dev/null +++ b/.changeset/plenty-wombats-grab.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +#wip Regenerate Keystone wrappers diff --git a/contracts/.changeset/old-pianos-trade.md b/contracts/.changeset/old-pianos-trade.md new file mode 100644 index 00000000000..10c0097bded --- /dev/null +++ b/contracts/.changeset/old-pianos-trade.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +#wip Add Capability Registry skeleton diff --git a/contracts/scripts/native_solc_compile_all_keystone b/contracts/scripts/native_solc_compile_all_keystone index 49bd6527843..1530b307dbd 100755 --- a/contracts/scripts/native_solc_compile_all_keystone +++ b/contracts/scripts/native_solc_compile_all_keystone @@ -28,5 +28,6 @@ compileContract () { "$ROOT"/contracts/src/v0.8/"$1" } +compileContract keystone/CapabilityRegistry.sol compileContract keystone/KeystoneForwarder.sol compileContract keystone/OCR3Capability.sol diff --git a/contracts/src/v0.8/keystone/CapabilityRegistry.sol b/contracts/src/v0.8/keystone/CapabilityRegistry.sol new file mode 100644 index 00000000000..7c870bed7fb --- /dev/null +++ b/contracts/src/v0.8/keystone/CapabilityRegistry.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {TypeAndVersionInterface} from "../interfaces/TypeAndVersionInterface.sol"; +import {OwnerIsCreator} from "../shared/access/OwnerIsCreator.sol"; + +struct Capability { + // Capability type, e.g. "data-streams-reports" + // bytes32(string); validation regex: ^[a-z0-9_\-:]{1,32}$ + // Not "type" because that's a reserved keyword in Solidity. + bytes32 capabilityType; + // Semver, e.g., "1.2.3" + // bytes32(string); must be valid Semver + max 32 characters. + bytes32 version; +} + +contract CapabilityRegistry is OwnerIsCreator, TypeAndVersionInterface { + mapping(bytes32 => Capability) private s_capabilities; + + event CapabilityAdded(bytes32 indexed capabilityId); + + function typeAndVersion() external pure override returns (string memory) { + return "CapabilityRegistry 1.0.0"; + } + + function addCapability(Capability calldata capability) external onlyOwner { + bytes32 capabilityId = getCapabilityID(capability.capabilityType, capability.version); + s_capabilities[capabilityId] = capability; + emit CapabilityAdded(capabilityId); + } + + function getCapability(bytes32 capabilityID) public view returns (Capability memory) { + return s_capabilities[capabilityID]; + } + + /// @notice This functions returns a Capability ID packed into a bytes32 for cheaper access + /// @return A unique identifier for the capability + function getCapabilityID(bytes32 capabilityType, bytes32 version) public pure returns (bytes32) { + return keccak256(abi.encodePacked(capabilityType, version)); + } +} diff --git a/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol b/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol new file mode 100644 index 00000000000..f5d539d8e34 --- /dev/null +++ b/contracts/src/v0.8/keystone/test/CapabilityRegistry.t.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import {Test} from "forge-std/Test.sol"; +import {Capability, CapabilityRegistry} from "../CapabilityRegistry.sol"; + +contract CapabilityRegistryTest is Test { + function setUp() public virtual {} + + function testAddCapability() public { + CapabilityRegistry capabilityRegistry = new CapabilityRegistry(); + + capabilityRegistry.addCapability(Capability("data-streams-reports", "1.0.0")); + + bytes32 capabilityId = capabilityRegistry.getCapabilityID(bytes32("data-streams-reports"), bytes32("1.0.0")); + Capability memory capability = capabilityRegistry.getCapability(capabilityId); + + assertEq(capability.capabilityType, "data-streams-reports"); + assertEq(capability.version, "1.0.0"); + } +} diff --git a/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go new file mode 100644 index 00000000000..45ae103ac56 --- /dev/null +++ b/core/gethwrappers/keystone/generated/keystone_capability_registry/keystone_capability_registry.go @@ -0,0 +1,768 @@ +// Code generated - DO NOT EDIT. +// This file is a generated binding and any manual changes will be lost. + +package keystone_capability_registry + +import ( + "errors" + "fmt" + "math/big" + "strings" + + ethereum "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/accounts/abi" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" + "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated" +) + +var ( + _ = errors.New + _ = big.NewInt + _ = strings.NewReader + _ = ethereum.NotFound + _ = bind.Bind + _ = common.Big1 + _ = types.BloomLookup + _ = event.NewSubscription + _ = abi.ConvertType +) + +type Capability struct { + CapabilityType [32]byte + Version [32]byte +} + +var CapabilityRegistryMetaData = &bind.MetaData{ + ABI: "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"capabilityId\",\"type\":\"bytes32\"}],\"name\":\"CapabilityAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferRequested\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"capability\",\"type\":\"tuple\"}],\"name\":\"addCapability\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityID\",\"type\":\"bytes32\"}],\"name\":\"getCapability\",\"outputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"internalType\":\"structCapability\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"capabilityType\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"version\",\"type\":\"bytes32\"}],\"name\":\"getCapabilityID\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"typeAndVersion\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", + Bin: "0x608060405234801561001057600080fd5b5033806000816100675760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615610097576100978161009f565b505050610148565b336001600160a01b038216036100f75760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161005e565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6105e5806101576000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806379ba50971161005b57806379ba5097146101275780638da5cb5b1461012f5780639cb7c5f414610157578063f2fde38b146101be57600080fd5b8063181f5a7714610082578063229111f5146100ca5780636e5f286914610112575b600080fd5b604080518082018252601881527f4361706162696c697479526567697374727920312e302e300000000000000000602082015290516100c191906104dc565b60405180910390f35b6101046100d8366004610548565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b6040519081526020016100c1565b61012561012036600461056a565b6101d1565b005b61012561024e565b60005460405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100c1565b6101a3610165366004610582565b604080518082019091526000808252602082015250600090815260026020908152604091829020825180840190935280548352600101549082015290565b604080518251815260209283015192810192909252016100c1565b6101256101cc36600461059b565b610350565b6101d9610364565b60408051823560208083018290528085013583850181905284518085038601815260609094018086528451948301949094206000818152600290935294822092835560019092019190915582917f65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff069190a25050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102d4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b610358610364565b610361816103e7565b50565b60005473ffffffffffffffffffffffffffffffffffffffff1633146103e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102cb565b565b3373ffffffffffffffffffffffffffffffffffffffff821603610466576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102cb565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600060208083528351808285015260005b81811015610509578581018301518582016040015282016104ed565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b6000806040838503121561055b57600080fd5b50508035926020909101359150565b60006040828403121561057c57600080fd5b50919050565b60006020828403121561059457600080fd5b5035919050565b6000602082840312156105ad57600080fd5b813573ffffffffffffffffffffffffffffffffffffffff811681146105d157600080fd5b939250505056fea164736f6c6343000813000a", +} + +var CapabilityRegistryABI = CapabilityRegistryMetaData.ABI + +var CapabilityRegistryBin = CapabilityRegistryMetaData.Bin + +func DeployCapabilityRegistry(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *CapabilityRegistry, error) { + parsed, err := CapabilityRegistryMetaData.GetAbi() + if err != nil { + return common.Address{}, nil, nil, err + } + if parsed == nil { + return common.Address{}, nil, nil, errors.New("GetABI returned nil") + } + + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(CapabilityRegistryBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &CapabilityRegistry{address: address, abi: *parsed, CapabilityRegistryCaller: CapabilityRegistryCaller{contract: contract}, CapabilityRegistryTransactor: CapabilityRegistryTransactor{contract: contract}, CapabilityRegistryFilterer: CapabilityRegistryFilterer{contract: contract}}, nil +} + +type CapabilityRegistry struct { + address common.Address + abi abi.ABI + CapabilityRegistryCaller + CapabilityRegistryTransactor + CapabilityRegistryFilterer +} + +type CapabilityRegistryCaller struct { + contract *bind.BoundContract +} + +type CapabilityRegistryTransactor struct { + contract *bind.BoundContract +} + +type CapabilityRegistryFilterer struct { + contract *bind.BoundContract +} + +type CapabilityRegistrySession struct { + Contract *CapabilityRegistry + CallOpts bind.CallOpts + TransactOpts bind.TransactOpts +} + +type CapabilityRegistryCallerSession struct { + Contract *CapabilityRegistryCaller + CallOpts bind.CallOpts +} + +type CapabilityRegistryTransactorSession struct { + Contract *CapabilityRegistryTransactor + TransactOpts bind.TransactOpts +} + +type CapabilityRegistryRaw struct { + Contract *CapabilityRegistry +} + +type CapabilityRegistryCallerRaw struct { + Contract *CapabilityRegistryCaller +} + +type CapabilityRegistryTransactorRaw struct { + Contract *CapabilityRegistryTransactor +} + +func NewCapabilityRegistry(address common.Address, backend bind.ContractBackend) (*CapabilityRegistry, error) { + abi, err := abi.JSON(strings.NewReader(CapabilityRegistryABI)) + if err != nil { + return nil, err + } + contract, err := bindCapabilityRegistry(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &CapabilityRegistry{address: address, abi: abi, CapabilityRegistryCaller: CapabilityRegistryCaller{contract: contract}, CapabilityRegistryTransactor: CapabilityRegistryTransactor{contract: contract}, CapabilityRegistryFilterer: CapabilityRegistryFilterer{contract: contract}}, nil +} + +func NewCapabilityRegistryCaller(address common.Address, caller bind.ContractCaller) (*CapabilityRegistryCaller, error) { + contract, err := bindCapabilityRegistry(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &CapabilityRegistryCaller{contract: contract}, nil +} + +func NewCapabilityRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*CapabilityRegistryTransactor, error) { + contract, err := bindCapabilityRegistry(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &CapabilityRegistryTransactor{contract: contract}, nil +} + +func NewCapabilityRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*CapabilityRegistryFilterer, error) { + contract, err := bindCapabilityRegistry(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &CapabilityRegistryFilterer{contract: contract}, nil +} + +func bindCapabilityRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := CapabilityRegistryMetaData.GetAbi() + if err != nil { + return nil, err + } + return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil +} + +func (_CapabilityRegistry *CapabilityRegistryRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilityRegistry.Contract.CapabilityRegistryCaller.contract.Call(opts, result, method, params...) +} + +func (_CapabilityRegistry *CapabilityRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.CapabilityRegistryTransactor.contract.Transfer(opts) +} + +func (_CapabilityRegistry *CapabilityRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.CapabilityRegistryTransactor.contract.Transact(opts, method, params...) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _CapabilityRegistry.Contract.contract.Call(opts, result, method, params...) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.contract.Transfer(opts) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.contract.Transact(opts, method, params...) +} + +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getCapability", capabilityID) + + if err != nil { + return *new(Capability), err + } + + out0 := *abi.ConvertType(out[0], new(Capability)).(*Capability) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapability(capabilityID [32]byte) (Capability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapability(capabilityID [32]byte) (Capability, error) { + return _CapabilityRegistry.Contract.GetCapability(&_CapabilityRegistry.CallOpts, capabilityID) +} + +func (_CapabilityRegistry *CapabilityRegistryCaller) GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "getCapabilityID", capabilityType, version) + + if err != nil { + return *new([32]byte), err + } + + out0 := *abi.ConvertType(out[0], new([32]byte)).(*[32]byte) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) GetCapabilityID(capabilityType [32]byte, version [32]byte) ([32]byte, error) { + return _CapabilityRegistry.Contract.GetCapabilityID(&_CapabilityRegistry.CallOpts, capabilityType, version) +} + +func (_CapabilityRegistry *CapabilityRegistryCaller) Owner(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "owner") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) Owner() (common.Address, error) { + return _CapabilityRegistry.Contract.Owner(&_CapabilityRegistry.CallOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) Owner() (common.Address, error) { + return _CapabilityRegistry.Contract.Owner(&_CapabilityRegistry.CallOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryCaller) TypeAndVersion(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _CapabilityRegistry.contract.Call(opts, &out, "typeAndVersion") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_CapabilityRegistry *CapabilityRegistrySession) TypeAndVersion() (string, error) { + return _CapabilityRegistry.Contract.TypeAndVersion(&_CapabilityRegistry.CallOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryCallerSession) TypeAndVersion() (string, error) { + return _CapabilityRegistry.Contract.TypeAndVersion(&_CapabilityRegistry.CallOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactor) AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "acceptOwnership") +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AcceptOwnership() (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AcceptOwnership(&_CapabilityRegistry.TransactOpts) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactor) AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "addCapability", capability) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) AddCapability(capability Capability) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) AddCapability(capability Capability) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.AddCapability(&_CapabilityRegistry.TransactOpts, capability) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { + return _CapabilityRegistry.contract.Transact(opts, "transferOwnership", to) +} + +func (_CapabilityRegistry *CapabilityRegistrySession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) +} + +func (_CapabilityRegistry *CapabilityRegistryTransactorSession) TransferOwnership(to common.Address) (*types.Transaction, error) { + return _CapabilityRegistry.Contract.TransferOwnership(&_CapabilityRegistry.TransactOpts, to) +} + +type CapabilityRegistryCapabilityAddedIterator struct { + Event *CapabilityRegistryCapabilityAdded + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryCapabilityAddedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryCapabilityAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryCapabilityAdded) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryCapabilityAddedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryCapabilityAddedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryCapabilityAdded struct { + CapabilityId [32]byte + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) { + + var capabilityIdRule []interface{} + for _, capabilityIdItem := range capabilityId { + capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "CapabilityAdded", capabilityIdRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryCapabilityAddedIterator{contract: _CapabilityRegistry.contract, event: "CapabilityAdded", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) { + + var capabilityIdRule []interface{} + for _, capabilityIdItem := range capabilityId { + capabilityIdRule = append(capabilityIdRule, capabilityIdItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "CapabilityAdded", capabilityIdRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryCapabilityAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityAdded", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) { + event := new(CapabilityRegistryCapabilityAdded) + if err := _CapabilityRegistry.contract.UnpackLog(event, "CapabilityAdded", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilityRegistryOwnershipTransferRequestedIterator struct { + Event *CapabilityRegistryOwnershipTransferRequested + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryOwnershipTransferRequested) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryOwnershipTransferRequestedIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryOwnershipTransferRequested struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryOwnershipTransferRequestedIterator{contract: _CapabilityRegistry.contract, event: "OwnershipTransferRequested", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "OwnershipTransferRequested", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryOwnershipTransferRequested) + if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseOwnershipTransferRequested(log types.Log) (*CapabilityRegistryOwnershipTransferRequested, error) { + event := new(CapabilityRegistryOwnershipTransferRequested) + if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferRequested", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +type CapabilityRegistryOwnershipTransferredIterator struct { + Event *CapabilityRegistryOwnershipTransferred + + contract *bind.BoundContract + event string + + logs chan types.Log + sub ethereum.Subscription + done bool + fail error +} + +func (it *CapabilityRegistryOwnershipTransferredIterator) Next() bool { + + if it.fail != nil { + return false + } + + if it.done { + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + default: + return false + } + } + + select { + case log := <-it.logs: + it.Event = new(CapabilityRegistryOwnershipTransferred) + if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil { + it.fail = err + return false + } + it.Event.Raw = log + return true + + case err := <-it.sub.Err(): + it.done = true + it.fail = err + return it.Next() + } +} + +func (it *CapabilityRegistryOwnershipTransferredIterator) Error() error { + return it.fail +} + +func (it *CapabilityRegistryOwnershipTransferredIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +type CapabilityRegistryOwnershipTransferred struct { + From common.Address + To common.Address + Raw types.Log +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferredIterator, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilityRegistry.contract.FilterLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return &CapabilityRegistryOwnershipTransferredIterator{contract: _CapabilityRegistry.contract, event: "OwnershipTransferred", logs: logs, sub: sub}, nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) { + + var fromRule []interface{} + for _, fromItem := range from { + fromRule = append(fromRule, fromItem) + } + var toRule []interface{} + for _, toItem := range to { + toRule = append(toRule, toItem) + } + + logs, sub, err := _CapabilityRegistry.contract.WatchLogs(opts, "OwnershipTransferred", fromRule, toRule) + if err != nil { + return nil, err + } + return event.NewSubscription(func(quit <-chan struct{}) error { + defer sub.Unsubscribe() + for { + select { + case log := <-logs: + + event := new(CapabilityRegistryOwnershipTransferred) + if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return err + } + event.Raw = log + + select { + case sink <- event: + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + case err := <-sub.Err(): + return err + case <-quit: + return nil + } + } + }), nil +} + +func (_CapabilityRegistry *CapabilityRegistryFilterer) ParseOwnershipTransferred(log types.Log) (*CapabilityRegistryOwnershipTransferred, error) { + event := new(CapabilityRegistryOwnershipTransferred) + if err := _CapabilityRegistry.contract.UnpackLog(event, "OwnershipTransferred", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +func (_CapabilityRegistry *CapabilityRegistry) ParseLog(log types.Log) (generated.AbigenLog, error) { + switch log.Topics[0] { + case _CapabilityRegistry.abi.Events["CapabilityAdded"].ID: + return _CapabilityRegistry.ParseCapabilityAdded(log) + case _CapabilityRegistry.abi.Events["OwnershipTransferRequested"].ID: + return _CapabilityRegistry.ParseOwnershipTransferRequested(log) + case _CapabilityRegistry.abi.Events["OwnershipTransferred"].ID: + return _CapabilityRegistry.ParseOwnershipTransferred(log) + + default: + return nil, fmt.Errorf("abigen wrapper received unknown log topic: %v", log.Topics[0]) + } +} + +func (CapabilityRegistryCapabilityAdded) Topic() common.Hash { + return common.HexToHash("0x65610e5677eedff94555572640e442f89848a109ef8593fa927ac30b2565ff06") +} + +func (CapabilityRegistryOwnershipTransferRequested) Topic() common.Hash { + return common.HexToHash("0xed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae1278") +} + +func (CapabilityRegistryOwnershipTransferred) Topic() common.Hash { + return common.HexToHash("0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0") +} + +func (_CapabilityRegistry *CapabilityRegistry) Address() common.Address { + return _CapabilityRegistry.address +} + +type CapabilityRegistryInterface interface { + GetCapability(opts *bind.CallOpts, capabilityID [32]byte) (Capability, error) + + GetCapabilityID(opts *bind.CallOpts, capabilityType [32]byte, version [32]byte) ([32]byte, error) + + Owner(opts *bind.CallOpts) (common.Address, error) + + TypeAndVersion(opts *bind.CallOpts) (string, error) + + AcceptOwnership(opts *bind.TransactOpts) (*types.Transaction, error) + + AddCapability(opts *bind.TransactOpts, capability Capability) (*types.Transaction, error) + + TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) + + FilterCapabilityAdded(opts *bind.FilterOpts, capabilityId [][32]byte) (*CapabilityRegistryCapabilityAddedIterator, error) + + WatchCapabilityAdded(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryCapabilityAdded, capabilityId [][32]byte) (event.Subscription, error) + + ParseCapabilityAdded(log types.Log) (*CapabilityRegistryCapabilityAdded, error) + + FilterOwnershipTransferRequested(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferRequestedIterator, error) + + WatchOwnershipTransferRequested(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferRequested, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferRequested(log types.Log) (*CapabilityRegistryOwnershipTransferRequested, error) + + FilterOwnershipTransferred(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*CapabilityRegistryOwnershipTransferredIterator, error) + + WatchOwnershipTransferred(opts *bind.WatchOpts, sink chan<- *CapabilityRegistryOwnershipTransferred, from []common.Address, to []common.Address) (event.Subscription, error) + + ParseOwnershipTransferred(log types.Log) (*CapabilityRegistryOwnershipTransferred, error) + + ParseLog(log types.Log) (generated.AbigenLog, error) + + Address() common.Address +} diff --git a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 8b1c830405d..98fd35e188b 100644 --- a/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/keystone/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,3 +1,4 @@ GETH_VERSION: 1.13.8 forwarder: ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin b4c900aae9e022f01abbac7993d41f93912247613ac6270b0c4da4ef6f2016e3 +keystone_capability_registry: ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin fbaf8eceb929494bdfe0028921a0742da525cb4ec1b6d57a1382eda46fa32c64 ocr3_capability: ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin 9dcbdf55bd5729ba266148da3f17733eb592c871c2108ccca546618628fd9ad2 diff --git a/core/gethwrappers/keystone/go_generate.go b/core/gethwrappers/keystone/go_generate.go index 0c49456f29c..679b678b8f2 100644 --- a/core/gethwrappers/keystone/go_generate.go +++ b/core/gethwrappers/keystone/go_generate.go @@ -6,3 +6,4 @@ package gethwrappers //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.abi ../../../contracts/solc/v0.8.19/KeystoneForwarder/KeystoneForwarder.bin KeystoneForwarder forwarder //go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.abi ../../../contracts/solc/v0.8.19/OCR3Capability/OCR3Capability.bin OCR3Capability ocr3_capability +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.abi ../../../contracts/solc/v0.8.19/CapabilityRegistry/CapabilityRegistry.bin CapabilityRegistry keystone_capability_registry From b2cd7ff3ac279ed05915f82493f8dcfdd4cb02f7 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Fri, 19 Apr 2024 11:18:33 -0500 Subject: [PATCH 21/26] bump cosmos (#12895) --- core/scripts/go.mod | 2 +- core/scripts/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- integration-tests/go.mod | 2 +- integration-tests/go.sum | 4 ++-- integration-tests/load/go.mod | 2 +- integration-tests/load/go.sum | 4 ++-- testdata/scripts/health/multi-chain.txtar | 10 ++++++++++ 9 files changed, 22 insertions(+), 12 deletions(-) diff --git a/core/scripts/go.mod b/core/scripts/go.mod index c7cd3a72d75..7e1ee1f10d7 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -257,7 +257,7 @@ require ( github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e // indirect diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 22bde9d5929..d43d5df8eea 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -1187,8 +1187,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= diff --git a/go.mod b/go.mod index c9695f0d98e..470a07da052 100644 --- a/go.mod +++ b/go.mod @@ -73,7 +73,7 @@ require ( github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.3 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e diff --git a/go.sum b/go.sum index b8a75291feb..7b7a1123baa 100644 --- a/go.sum +++ b/go.sum @@ -1182,8 +1182,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= diff --git a/integration-tests/go.mod b/integration-tests/go.mod index 29da646554f..e0c50d14bc5 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -378,7 +378,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e // indirect diff --git a/integration-tests/go.sum b/integration-tests/go.sum index b650c96f43d..af600c8b550 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -1521,8 +1521,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 729642044cf..da76545c616 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -367,7 +367,7 @@ require ( github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect github.com/smartcontractkit/chain-selectors v1.0.10 // indirect - github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 // indirect + github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 // indirect github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 // indirect github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 // indirect github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e // indirect diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index 5cd4c98c4a1..cdb5a488d37 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -1504,8 +1504,8 @@ github.com/smartcontractkit/chainlink-automation v1.0.3 h1:h/ijT0NiyV06VxYVgcNfs github.com/smartcontractkit/chainlink-automation v1.0.3/go.mod h1:RjboV0Qd7YP+To+OrzHGXaxUxoSONveCoAK2TQ1INLU= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e h1:nHs5mFOR7FPII20GrCGIPywDW43MhEUlD7DqHnTgu6Q= github.com/smartcontractkit/chainlink-common v0.1.7-0.20240419105123-fc5d616c7d2e/go.mod h1:GTDBbovHUSAUk+fuGIySF2A/whhdtHGaWmU61BoERks= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8 h1:I326nw5GwHQHsLKHwtu5Sb9EBLylC8CfUd7BFAS0jtg= -github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240213120401-01a23955f9f8/go.mod h1:a65NtrK4xZb01mf0dDNghPkN2wXgcqFQ55ADthVBgMc= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92 h1:MvaNzuaQh1vX4CAYLM8qFd99cf0ZF1JNwtDZtLU7WvU= +github.com/smartcontractkit/chainlink-cosmos v0.4.1-0.20240419131812-73d148593d92/go.mod h1:uATrrJ8IsuBkOBJ46USuf73gz9gZy5k5bzGE5/ji/rc= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540 h1:xFSv8561jsLtF6gYZr/zW2z5qUUAkcFkApin2mnbYTo= github.com/smartcontractkit/chainlink-data-streams v0.0.0-20240220203239-09be0ea34540/go.mod h1:sjAmX8K2kbQhvDarZE1ZZgDgmHJ50s0BBc/66vKY2ek= github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h1:1BcjXuviSAKttOX7BZoVHRZZGfxqoA2+AL8tykmkdoc= diff --git a/testdata/scripts/health/multi-chain.txtar b/testdata/scripts/health/multi-chain.txtar index 112d9e3cdb1..fd48c0ad1ce 100644 --- a/testdata/scripts/health/multi-chain.txtar +++ b/testdata/scripts/health/multi-chain.txtar @@ -61,6 +61,7 @@ URL = 'http://stark.node' -- out.txt -- ok Cosmos.Foo.Chain +ok Cosmos.Foo.Relayer ok Cosmos.Foo.Txm ok EVM.1 ok EVM.1.BalanceMonitor @@ -97,6 +98,15 @@ ok TelemetryManager "output": "" } }, + { + "type": "checks", + "id": "Cosmos.Foo.Relayer", + "attributes": { + "name": "Cosmos.Foo.Relayer", + "status": "passing", + "output": "" + } + }, { "type": "checks", "id": "Cosmos.Foo.Txm", From facaf9a86085b709efb66cde5bedd69857310ed0 Mon Sep 17 00:00:00 2001 From: Cedric Date: Fri, 19 Apr 2024 17:53:20 +0100 Subject: [PATCH 22/26] [fix] Fix engine panic when we get a zero response (#12890) --- core/services/workflows/engine.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/services/workflows/engine.go b/core/services/workflows/engine.go index 71d9ab9463e..4694ca4286f 100644 --- a/core/services/workflows/engine.go +++ b/core/services/workflows/engine.go @@ -219,7 +219,12 @@ func (e *Engine) loop(ctx context.Context) { case <-ctx.Done(): e.logger.Debugw("shutting down loop") return - case resp := <-e.triggerEvents: + case resp, isOpen := <-e.triggerEvents: + if !isOpen { + e.logger.Errorf("trigger events channel is no longer open, skipping") + continue + } + if resp.Err != nil { e.logger.Errorf("trigger event was an error; not executing", resp.Err) continue From 36c5ca6e639c08de697b6ad98ab4047e997a7813 Mon Sep 17 00:00:00 2001 From: frank zhu Date: Fri, 19 Apr 2024 10:18:08 -0700 Subject: [PATCH 23/26] add kubeconform gha to validate k8s manifests (#12865) * add kubeconform gha to validate k8s manifests * add regexSkipDir input * fix * use .github action instead * fix metrics-job-name * fix * split job * use yq for helm repo add * fix needs * add checkout * refactor without add-helm-repos step * edit * pin versio * update ci-kubeconform version with summary --- .github/workflows/helm-chart.yml | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/.github/workflows/helm-chart.yml b/.github/workflows/helm-chart.yml index 1a12a512e39..f0dd25c5dbb 100644 --- a/.github/workflows/helm-chart.yml +++ b/.github/workflows/helm-chart.yml @@ -9,24 +9,29 @@ on: jobs: ci-lint-helm-charts: runs-on: ubuntu-latest - permissions: - id-token: write - contents: read - actions: read steps: - - name: Add repositories - run: | - helm repo add mockserver https://www.mock-server.com - helm repo add opentelemetry-collector https://open-telemetry.github.io/opentelemetry-helm-charts - helm repo add tempo https://grafana.github.io/helm-charts - helm repo add grafana https://grafana.github.io/helm-charts - name: ci-lint-helm-charts - uses: smartcontractkit/.github/actions/ci-lint-charts@6b08487b176ef7cad086526d0b54ddff6691c044 # ci-lint-charts@0.1.2 + uses: smartcontractkit/.github/actions/ci-lint-charts@7fa39741b11e66ed59f8aad786d4b9356c389f3f # ci-lint-charts@0.2.0 with: # chart testing inputs chart-testing-extra-args: "--lint-conf=lintconf.yaml" + charts-dir: charts/chainlink-cluster # grafana inputs metrics-job-name: ci-lint-helm-charts gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} + + ci-kubeconform: + runs-on: ubuntu-latest + steps: + - name: ci-kubeconform + uses: smartcontractkit/.github/actions/ci-kubeconform@1ae8a9a984814c4daf50aa96f03be2cba0ef3fec # ci-kubeconform@0.2.0 + with: + # kubeform inputs + charts-dir: charts/chainlink-cluster + # grafana inputs + metrics-job-name: ci-kubeconform + gc-basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} + gc-host: ${{ secrets.GRAFANA_INTERNAL_HOST }} + gc-org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} From 47c4a727b59e1f4bd977b12f7cf1af12b82a76a5 Mon Sep 17 00:00:00 2001 From: Sergey Kudasov Date: Fri, 19 Apr 2024 20:21:19 +0200 Subject: [PATCH 24/26] use zig from nix and do not fail build on unused build params (#12899) --- .goreleaser.devspace.yaml | 4 ++-- shell.nix | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.goreleaser.devspace.yaml b/.goreleaser.devspace.yaml index 1c6b4768d98..bca65e90454 100644 --- a/.goreleaser.devspace.yaml +++ b/.goreleaser.devspace.yaml @@ -24,8 +24,8 @@ builds: post: ./tools/bin/goreleaser_utils build_post_hook {{ dir .Path }} {{ .Os }} {{ .Arch }} env: - CGO_ENABLED=1 - - CC=$ZIG_EXEC cc -target x86_64-linux-gnu - - CCX=$ZIG_EXEC c++ -target x86_64-linux-gnu + - CC=$ZIG_EXEC cc -target x86_64-linux-gnu -Wno-error=unused-command-line-argument + - CCX=$ZIG_EXEC c++ -target x86_64-linux-gnu -Wno-error=unused-command-line-argument flags: - -trimpath - -buildmode=pie diff --git a/shell.nix b/shell.nix index ca785283fd5..69bf202351d 100644 --- a/shell.nix +++ b/shell.nix @@ -42,6 +42,9 @@ mkShell' { kubectl kubernetes-helm + # cross-compiling, used in CRIB + zig + # gofuzz ] ++ lib.optionals stdenv.isLinux [ # some dependencies needed for node-gyp on pnpm install From 1fce16e735e417553c00680a3fcae2e081353095 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Fri, 19 Apr 2024 15:30:40 -0500 Subject: [PATCH 25/26] core/services/keystore: switch to sqlutil.DataStore (#12810) --- .changeset/lucky-ghosts-give.md | 5 + core/chains/evm/log/helpers_test.go | 2 +- core/chains/evm/log/orm_test.go | 7 +- core/chains/evm/monitor/balance_test.go | 18 +-- core/chains/evm/txmgr/broadcaster_test.go | 36 ++--- core/chains/evm/txmgr/confirmer_test.go | 45 +++--- core/chains/evm/txmgr/evm_tx_store_test.go | 151 ++++++------------ core/chains/evm/txmgr/reaper_test.go | 4 +- core/chains/evm/txmgr/resender_test.go | 8 +- core/chains/evm/txmgr/tracker_test.go | 3 +- core/chains/evm/txmgr/txmgr_test.go | 10 +- core/chains/evm/types/models_test.go | 4 +- core/cmd/cosmos_keys_commands_test.go | 16 +- core/cmd/cosmos_transaction_commands_test.go | 3 +- core/cmd/csa_keys_commands_test.go | 9 +- core/cmd/dkgencrypt_keys_commands_test.go | 16 +- core/cmd/dkgsign_keys_commands_test.go | 16 +- core/cmd/key_store_authenticator.go | 9 +- core/cmd/ocr2_keys_commands_test.go | 16 +- core/cmd/ocr2vrf_configure_commands.go | 10 +- core/cmd/ocr_keys_commands_test.go | 12 +- core/cmd/p2p_keys_commands_test.go | 12 +- core/cmd/shell.go | 2 +- core/cmd/shell_local.go | 18 +-- core/cmd/shell_local_test.go | 10 +- core/cmd/shell_remote_test.go | 3 +- core/cmd/solana_keys_commands_test.go | 16 +- core/cmd/solana_transaction_commands_test.go | 4 +- core/cmd/starknet_keys_commands_test.go | 16 +- core/internal/cltest/cltest.go | 31 ++-- core/internal/cltest/job_factories.go | 2 +- core/internal/features/features_test.go | 11 +- .../features/ocr2/features_ocr2_test.go | 3 +- core/internal/testutils/testutils.go | 11 +- core/scripts/vrfv2/testnet/main.go | 10 +- core/scripts/vrfv2plus/testnet/main.go | 10 +- core/services/blockhashstore/bhs_test.go | 8 +- core/services/blockhashstore/delegate_test.go | 2 +- .../relayer_chain_interoperators_test.go | 2 +- core/services/cron/cron_test.go | 2 +- core/services/directrequest/delegate_test.go | 4 +- core/services/feeds/orm_test.go | 8 +- core/services/feeds/service_test.go | 2 +- .../fluxmonitorv2/flux_monitor_test.go | 6 +- core/services/fluxmonitorv2/key_store_test.go | 6 +- core/services/fluxmonitorv2/orm_test.go | 5 +- core/services/functions/listener_test.go | 2 +- core/services/job/helpers_test.go | 6 +- core/services/job/job_orm_test.go | 132 ++++++++------- .../job/job_pipeline_orm_integration_test.go | 5 +- core/services/job/kv_orm_test.go | 2 +- core/services/job/runner_integration_test.go | 21 +-- core/services/job/spawner_test.go | 9 +- core/services/keeper/orm_test.go | 56 +++---- .../registry_synchronizer_helper_test.go | 2 +- core/services/keeper/upkeep_executer_test.go | 2 +- core/services/keystore/cosmos.go | 30 ++-- core/services/keystore/cosmos_test.go | 39 +++-- core/services/keystore/csa.go | 31 ++-- core/services/keystore/csa_test.go | 48 +++--- core/services/keystore/dkgencrypt.go | 31 ++-- core/services/keystore/dkgencrypt_test.go | 34 ++-- core/services/keystore/dkgsign.go | 31 ++-- core/services/keystore/dkgsign_test.go | 35 ++-- core/services/keystore/eth.go | 65 ++++---- core/services/keystore/eth_test.go | 62 ++++--- core/services/keystore/helpers_test.go | 13 +- core/services/keystore/keystoretest.go | 27 ++-- core/services/keystore/master.go | 49 +++--- core/services/keystore/master_test.go | 31 ++-- core/services/keystore/mocks/cosmos.go | 76 ++++----- core/services/keystore/mocks/csa.go | 76 ++++----- core/services/keystore/mocks/dkg_encrypt.go | 76 ++++----- core/services/keystore/mocks/dkg_sign.go | 76 ++++----- core/services/keystore/mocks/eth.go | 53 ++---- core/services/keystore/mocks/master.go | 30 ++-- core/services/keystore/mocks/ocr.go | 79 ++++----- core/services/keystore/mocks/ocr2.go | 67 ++++---- core/services/keystore/mocks/p2p.go | 79 ++++----- core/services/keystore/mocks/solana.go | 74 ++++----- core/services/keystore/mocks/starknet.go | 79 ++++----- core/services/keystore/mocks/vrf.go | 65 ++++---- core/services/keystore/ocr.go | 31 ++-- core/services/keystore/ocr2.go | 35 ++-- core/services/keystore/ocr2_test.go | 50 +++--- core/services/keystore/ocr_test.go | 42 ++--- core/services/keystore/orm.go | 34 ++-- core/services/keystore/p2p.go | 35 ++-- core/services/keystore/p2p_test.go | 51 +++--- core/services/keystore/solana.go | 30 ++-- core/services/keystore/solana_test.go | 41 ++--- core/services/keystore/starknet.go | 30 ++-- core/services/keystore/starknet_test.go | 30 ++-- core/services/keystore/vrf.go | 25 +-- core/services/keystore/vrf_test.go | 47 +++--- core/services/ocr/database_test.go | 10 +- core/services/ocr2/database_test.go | 6 +- core/services/ocr2/delegate_test.go | 5 +- .../ocr2/plugins/dkg/config/config_test.go | 10 +- .../v1/internal/testutils.go | 5 +- .../generic/pipeline_runner_adapter_test.go | 5 +- .../plugins/ocr2keeper/integration_test.go | 5 +- .../internal/ocr2vrf_integration_test.go | 6 +- core/services/ocrcommon/peer_wrapper_test.go | 41 +++-- core/services/ocrcommon/transmitter_test.go | 13 +- core/services/pipeline/orm_test.go | 6 +- core/services/pipeline/runner_test.go | 8 +- .../promreporter/prom_reporter_test.go | 5 +- .../functions/contract_transmitter_test.go | 10 +- .../relay/evm/relayer_extender_test.go | 5 +- core/services/vrf/delegate_test.go | 19 +-- .../services/vrf/proof/proof_response_test.go | 8 +- core/services/vrf/v1/integration_test.go | 3 +- .../vrf/v2/integration_helpers_test.go | 8 +- .../vrf/v2/integration_v2_plus_test.go | 6 +- .../v2/integration_v2_reverted_txns_test.go | 3 +- core/services/vrf/v2/integration_v2_test.go | 13 +- .../vrf/v2/listener_v2_log_listener_test.go | 7 +- core/services/vrf/v2/listener_v2_test.go | 22 ++- core/web/build_info_controller_test.go | 9 +- core/web/cosmos_chains_controller_test.go | 3 +- core/web/cosmos_keys_controller_test.go | 11 +- core/web/csa_keys_controller.go | 6 +- core/web/dkgencrypt_keys_controller_test.go | 5 +- core/web/dkgsign_keys_controller_test.go | 5 +- core/web/eth_keys_controller_test.go | 89 +++++++---- core/web/evm_chains_controller_test.go | 3 +- core/web/evm_forwarders_controller_test.go | 3 +- core/web/evm_transactions_controller_test.go | 13 +- core/web/jobs_controller_test.go | 22 +-- core/web/keys_controller.go | 16 +- core/web/loop_registry_test.go | 3 +- core/web/ocr2_keys_controller.go | 9 +- core/web/ocr2_keys_controller_test.go | 6 +- core/web/ocr_keys_controller.go | 9 +- core/web/ocr_keys_controller_test.go | 6 +- core/web/p2p_keys_controller.go | 9 +- core/web/p2p_keys_controller_test.go | 10 +- core/web/pipeline_runs_controller_test.go | 5 +- core/web/resolver/csa_keys_test.go | 9 +- core/web/resolver/mutation.go | 20 +-- core/web/resolver/ocr2_keys_test.go | 14 +- core/web/resolver/ocr_test.go | 7 +- core/web/resolver/p2p_test.go | 7 +- core/web/resolver/vrf_test.go | 7 +- core/web/solana_keys_controller_test.go | 16 +- core/web/starknet_keys_controller_test.go | 10 +- core/web/vrf_keys_controller.go | 9 +- 148 files changed, 1696 insertions(+), 1552 deletions(-) create mode 100644 .changeset/lucky-ghosts-give.md diff --git a/.changeset/lucky-ghosts-give.md b/.changeset/lucky-ghosts-give.md new file mode 100644 index 00000000000..2ce47a6978b --- /dev/null +++ b/.changeset/lucky-ghosts-give.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +core/services/keystore: switch to sqlutil.DataStore #internal diff --git a/core/chains/evm/log/helpers_test.go b/core/chains/evm/log/helpers_test.go index 85c2fe783bb..8919b848aca 100644 --- a/core/chains/evm/log/helpers_test.go +++ b/core/chains/evm/log/helpers_test.go @@ -94,7 +94,7 @@ func newBroadcasterHelperWithEthClient(t *testing.T, ethClient evmclient.Client, db := pgtest.NewSqlxDB(t) orm := log.NewORM(db, cltest.FixtureChainID) lb := log.NewTestBroadcaster(orm, ethClient, config.EVM(), lggr, highestSeenHead, mailMon) - kst := cltest.NewKeyStore(t, db, globalConfig.Database()) + kst := cltest.NewKeyStore(t, db) cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{ Client: ethClient, diff --git a/core/chains/evm/log/orm_test.go b/core/chains/evm/log/orm_test.go index 1a6d927cd50..dc3611e8e6f 100644 --- a/core/chains/evm/log/orm_test.go +++ b/core/chains/evm/log/orm_test.go @@ -13,14 +13,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/log" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) func TestORM_broadcasts(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() orm := log.NewORM(db, cltest.FixtureChainID) @@ -108,8 +106,7 @@ func TestORM_pending(t *testing.T) { func TestORM_MarkUnconsumed(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() orm := log.NewORM(db, cltest.FixtureChainID) diff --git a/core/chains/evm/monitor/balance_test.go b/core/chains/evm/monitor/balance_test.go index 85e0ec669bf..a27e2cec9a7 100644 --- a/core/chains/evm/monitor/balance_test.go +++ b/core/chains/evm/monitor/balance_test.go @@ -20,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/monitor" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -35,11 +34,9 @@ func newEthClientMock(t *testing.T) *evmclimocks.Client { func TestBalanceMonitor_Start(t *testing.T) { t.Parallel() - cfg := configtest.NewGeneralConfig(t, nil) - t.Run("updates balance from nil for multiple keys", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := newEthClientMock(t) _, k1Addr := cltest.MustInsertRandomKey(t, ethKeyStore) _, k0Addr := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -66,7 +63,7 @@ func TestBalanceMonitor_Start(t *testing.T) { t.Run("handles nil head", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := newEthClientMock(t) _, k0Addr := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -85,7 +82,7 @@ func TestBalanceMonitor_Start(t *testing.T) { t.Run("cancelled context", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := newEthClientMock(t) _, k0Addr := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -114,7 +111,7 @@ func TestBalanceMonitor_Start(t *testing.T) { t.Run("recovers on error", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := newEthClientMock(t) _, k0Addr := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -136,11 +133,9 @@ func TestBalanceMonitor_Start(t *testing.T) { func TestBalanceMonitor_OnNewLongestChain_UpdatesBalance(t *testing.T) { t.Parallel() - cfg := configtest.NewGeneralConfig(t, nil) - t.Run("updates balance for multiple keys", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := newEthClientMock(t) _, k0Addr := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -190,8 +185,7 @@ func TestBalanceMonitor_FewerRPCCallsWhenBehind(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/chains/evm/txmgr/broadcaster_test.go b/core/chains/evm/txmgr/broadcaster_test.go index 070c2c37473..14968126bf9 100644 --- a/core/chains/evm/txmgr/broadcaster_test.go +++ b/core/chains/evm/txmgr/broadcaster_test.go @@ -81,7 +81,7 @@ func TestEthBroadcaster_Lifecycle(t *testing.T) { txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) @@ -139,7 +139,7 @@ func TestEthBroadcaster_LoadNextSequenceMapFailure_StartupSuccess(t *testing.T) txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), evmcfg.EVM().GasEstimator(), ethKeyStore, estimator) @@ -170,7 +170,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) ctx := testutils.Context(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -525,7 +525,7 @@ func TestEthBroadcaster_TransmitChecking(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) ctx := testutils.Context(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -611,7 +611,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_OptimisticLockingOnEthTx(t *testi ccfg := evmtest.NewChainScopedConfig(t, cfg) evmcfg := txmgr.NewEvmTxmConfig(ccfg.EVM()) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) estimator := gasmocks.NewEvmFeeEstimator(t) txBuilder := txmgr.NewEvmTxAttemptBuilder(*ethClient.ConfiguredChainID(), ccfg.EVM().GasEstimator(), ethKeyStore, estimator) @@ -674,7 +674,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Success_WithMultiplier(t *testing }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -723,7 +723,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) firstInProgress := txmgr.Tx{ @@ -758,7 +758,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -797,7 +797,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -834,7 +834,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -870,7 +870,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -908,7 +908,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) @@ -944,7 +944,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_ResumingFromCrash(t *testing.T) { db := pgtest.NewSqlxDB(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Nonce: nextNonce.Int64()}.MustInsertWithState(t, ethKeyStore) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -1013,7 +1013,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_Errors(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1655,7 +1655,7 @@ func TestEthBroadcaster_ProcessUnstartedEthTxs_KeystoreErrors(t *testing.T) { cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - realKeystore := cltest.NewKeyStore(t, db, cfg.Database()) + realKeystore := cltest.NewKeyStore(t, db) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, realKeystore.Eth()) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1712,7 +1712,7 @@ func TestEthBroadcaster_Trigger(t *testing.T) { cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) lggr := logger.Test(t) nonceTracker := txmgr.NewNonceTracker(lggr, txStore, txmgr.NewEvmTxmClient(ethClient)) @@ -1735,7 +1735,7 @@ func TestEthBroadcaster_SyncNonce(t *testing.T) { evmTxmCfg := txmgr.NewEvmTxmConfig(evmcfg.EVM()) txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + kst := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.RandomKey{Disabled: false}.MustInsertWithState(t, kst) estimator := gas.NewEvmFeeEstimator(lggr, func(lggr logger.Logger) gas.EvmEstimator { @@ -1770,7 +1770,7 @@ func TestEthBroadcaster_NonceTracker_InProgressTx(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) diff --git a/core/chains/evm/txmgr/confirmer_test.go b/core/chains/evm/txmgr/confirmer_test.go index 89e88d5a6dc..f368aea9c57 100644 --- a/core/chains/evm/txmgr/confirmer_test.go +++ b/core/chains/evm/txmgr/confirmer_test.go @@ -118,7 +118,7 @@ func TestEthConfirmer_Lifecycle(t *testing.T) { txStore := newTxStore(t, db) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() // Add some fromAddresses cltest.MustInsertRandomKey(t, ethKeyStore) @@ -188,7 +188,7 @@ func TestEthConfirmer_CheckForReceipts(t *testing.T) { txStore := cltest.NewTestTxStore(t, db) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -601,7 +601,7 @@ func TestEthConfirmer_CheckForReceipts_batching(t *testing.T) { }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -664,7 +664,7 @@ func TestEthConfirmer_CheckForReceipts_HandlesNonFwdTxsWithForwardingEnabled(t * }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -714,7 +714,7 @@ func TestEthConfirmer_CheckForReceipts_only_likely_confirmed(t *testing.T) { }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -770,7 +770,7 @@ func TestEthConfirmer_CheckForReceipts_should_not_check_for_likely_unconfirmed(t config := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -797,7 +797,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt_scoped_to_key(t db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress1_1 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) _, fromAddress1_2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -866,7 +866,7 @@ func TestEthConfirmer_CheckForReceipts_confirmed_missing_receipt(t *testing.T) { }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1126,7 +1126,7 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt(t *testing.T) { }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1205,7 +1205,7 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_batchSendTransactions_fails(t }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1269,7 +1269,7 @@ func TestEthConfirmer_CheckConfirmedMissingReceipt_smallEvmRPCBatchSize_middleBa }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1341,7 +1341,7 @@ func TestEthConfirmer_FindTxsRequiringRebroadcast(t *testing.T) { evmcfg := evmtest.NewChainScopedConfig(t, cfg) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) evmFromAddress := fromAddress @@ -1639,7 +1639,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing ctx := testutils.Context(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) kst := ksmocks.NewEth(t) @@ -1686,7 +1686,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_WithConnectivityCheck(t *testing ctx := testutils.Context(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) kst := ksmocks.NewEth(t) @@ -1735,7 +1735,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_MaxFeeScenario(t *testing.T) { ctx := testutils.Context(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -1803,7 +1803,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary(t *testing.T) { ctx := testutils.Context(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -2414,7 +2414,7 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmcfg := evmtest.NewChainScopedConfig(t, cfg) @@ -2521,12 +2521,11 @@ func TestEthConfirmer_RebroadcastWhereNecessary_TerminallyUnderpriced_ThenGoesTh func TestEthConfirmer_RebroadcastWhereNecessary_WhenOutOfEth(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) ctx := testutils.Context(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -2660,11 +2659,10 @@ func TestEthConfirmer_EnsureConfirmedTransactionsInLongestChain(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) ctx := testutils.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -2835,10 +2833,9 @@ func TestEthConfirmer_ForceRebroadcast(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) config := newTestChainScopedConfig(t) @@ -2939,7 +2936,7 @@ func TestEthConfirmer_ResumePendingRuns(t *testing.T) { config := configtest.NewTestGeneralConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/chains/evm/txmgr/evm_tx_store_test.go b/core/chains/evm/txmgr/evm_tx_store_test.go index ff5c7ec4abc..1d1d85c0960 100644 --- a/core/chains/evm/txmgr/evm_tx_store_test.go +++ b/core/chains/evm/txmgr/evm_tx_store_test.go @@ -8,6 +8,10 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/guregu/null.v4" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-common/pkg/logger" @@ -27,18 +31,12 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/pipeline" - - "github.com/google/uuid" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "gopkg.in/guregu/null.v4" ) func TestORM_TransactionsWithAttempts(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ctx := testutils.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -82,9 +80,8 @@ func TestORM_TransactionsWithAttempts(t *testing.T) { func TestORM_Transactions(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ctx := testutils.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -122,8 +119,7 @@ func TestORM(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) orm := cltest.NewTestTxStore(t, db) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) ctx := testutils.Context(t) @@ -190,9 +186,8 @@ func TestORM(t *testing.T) { func TestORM_FindTxAttemptConfirmedByTxIDs(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) orm := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ctx := testutils.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -241,11 +236,10 @@ func TestORM_FindTxAttemptsRequiringResend(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - logCfg := pgtest.NewQConfig(true) txStore := cltest.NewTestTxStore(t, db) ctx := testutils.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db, logCfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -329,8 +323,7 @@ func TestORM_UpdateBroadcastAts(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) orm := cltest.NewTestTxStore(t, db) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -380,7 +373,7 @@ func TestORM_SetBroadcastBeforeBlockNum(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) etx := cltest.MustInsertUnconfirmedEthTxWithBroadcastLegacyAttempt(t, txStore, 0, fromAddress) @@ -447,9 +440,8 @@ func TestORM_FindTxAttemptsConfirmedMissingReceipt(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -471,9 +463,8 @@ func TestORM_UpdateTxsUnconfirmed(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) originalBroadcastAt := time.Unix(1616509100, 0) @@ -491,9 +482,8 @@ func TestORM_FindTxAttemptsRequiringReceiptFetch(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -512,9 +502,8 @@ func TestORM_SaveFetchedReceipts(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ctx := testutils.Context(t) @@ -547,9 +536,8 @@ func TestORM_MarkAllConfirmedMissingReceipt(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) ctx := testutils.Context(t) @@ -578,9 +566,8 @@ func TestORM_PreloadTxes(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("loads eth transaction", func(t *testing.T) { @@ -612,9 +599,8 @@ func TestORM_GetInProgressTxAttempts(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -633,9 +619,8 @@ func TestORM_FindTxesPendingCallback(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -709,7 +694,7 @@ func Test_FindTxWithIdempotencyKey(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("returns nil if no results", func(t *testing.T) { @@ -737,9 +722,8 @@ func TestORM_FindTxWithSequence(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("returns nil if no results", func(t *testing.T) { @@ -762,9 +746,8 @@ func TestORM_UpdateTxForRebroadcast(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) ctx := testutils.Context(t) @@ -827,9 +810,8 @@ func TestORM_FindTransactionsConfirmedInBlockRange(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -863,9 +845,8 @@ func TestORM_FindEarliestUnconfirmedBroadcastTime(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -887,9 +868,8 @@ func TestORM_FindEarliestUnconfirmedTxAttemptBlock(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) _, fromAddress2 := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -919,9 +899,8 @@ func TestORM_SaveInsufficientEthAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -944,9 +923,8 @@ func TestORM_SaveSentAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -970,9 +948,8 @@ func TestORM_SaveConfirmedMissingReceiptAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) defaultDuration, err := time.ParseDuration("5s") require.NoError(t, err) @@ -996,9 +973,8 @@ func TestORM_DeleteInProgressAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("deletes in_progress attempt", func(t *testing.T) { @@ -1019,9 +995,8 @@ func TestORM_SaveInProgressAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("saves new in_progress attempt if attempt is new", func(t *testing.T) { @@ -1061,9 +1036,8 @@ func TestORM_FindTxsRequiringGasBump(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1101,11 +1075,10 @@ func TestEthConfirmer_FindTxsRequiringResubmissionDueToInsufficientEth(t *testin t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) ctx := testutils.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1163,10 +1136,9 @@ func TestORM_MarkOldTxesMissingReceiptAsErrored(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) ctx := testutils.Context(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1200,9 +1172,8 @@ func TestORM_LoadEthTxesAttempts(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("load eth tx attempt", func(t *testing.T) { @@ -1254,9 +1225,8 @@ func TestORM_SaveReplacementInProgressAttempt(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("replace eth tx attempt", func(t *testing.T) { @@ -1278,9 +1248,8 @@ func TestORM_FindNextUnstartedTransactionFromAddress(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1306,9 +1275,8 @@ func TestORM_UpdateTxFatalError(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1331,9 +1299,8 @@ func TestORM_UpdateTxAttemptInProgressToBroadcast(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("update successful", func(t *testing.T) { @@ -1363,9 +1330,8 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) nonce := evmtypes.Nonce(123) @@ -1397,9 +1363,8 @@ func TestORM_UpdateTxUnstartedToInProgress(t *testing.T) { }) db = pgtest.NewSqlxDB(t) - cfg = newTestChainScopedConfig(t) txStore = cltest.NewTestTxStore(t, db) - ethKeyStore = cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore = cltest.NewKeyStore(t, db).Eth() _, fromAddress = cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("update replaces abandoned tx with same hash", func(t *testing.T) { @@ -1452,9 +1417,8 @@ func TestORM_GetTxInProgress(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("gets 0 in progress eth transaction", func(t *testing.T) { @@ -1476,9 +1440,8 @@ func TestORM_GetAbandonedTransactionsByBatch(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) _, enabled := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1534,9 +1497,8 @@ func TestORM_GetTxByID(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("no transaction", func(t *testing.T) { @@ -1557,9 +1519,8 @@ func TestORM_GetFatalTransactions(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) t.Run("gets 0 fatal eth transactions", func(t *testing.T) { @@ -1580,9 +1541,8 @@ func TestORM_HasInProgressTransaction(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1605,9 +1565,8 @@ func TestORM_CountUnconfirmedTransactions(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -1626,9 +1585,8 @@ func TestORM_CountTransactionsByState(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress1 := cltest.MustInsertRandomKey(t, ethKeyStore) _, fromAddress2 := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -1647,9 +1605,8 @@ func TestORM_CountUnstartedTransactions(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -1668,9 +1625,8 @@ func TestORM_CheckTxQueueCapacity(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, otherAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -1764,9 +1720,8 @@ func TestORM_CreateTransaction(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := newTxStore(t, db) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + kst := cltest.NewKeyStore(t, db) _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) toAddress := testutils.NewAddress() @@ -1864,9 +1819,8 @@ func TestORM_PruneUnstartedTxQueue(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := txmgr.NewTxStore(db, logger.Test(t)) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() evmtest.NewEthClientMockWithDefaultChain(t) _, fromAddress := cltest.MustInsertRandomKeyReturningState(t, ethKeyStore) @@ -1893,9 +1847,8 @@ func TestORM_FindTxesWithAttemptsAndReceiptsByIdsAndState(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ctx := testutils.Context(t) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/chains/evm/txmgr/reaper_test.go b/core/chains/evm/txmgr/reaper_test.go index 7918ed0e2ca..b3ce48b702c 100644 --- a/core/chains/evm/txmgr/reaper_test.go +++ b/core/chains/evm/txmgr/reaper_test.go @@ -15,7 +15,6 @@ import ( txmgrmocks "github.com/smartcontractkit/chainlink/v2/common/txmgr/types/mocks" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -44,9 +43,8 @@ func TestReaper_ReapTxes(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, from := cltest.MustInsertRandomKey(t, ethKeyStore) var nonce int64 diff --git a/core/chains/evm/txmgr/resender_test.go b/core/chains/evm/txmgr/resender_test.go index 57605c61785..8df5344f57c 100644 --- a/core/chains/evm/txmgr/resender_test.go +++ b/core/chains/evm/txmgr/resender_test.go @@ -30,9 +30,8 @@ func Test_EthResender_resendUnconfirmed(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - logCfg := pgtest.NewQConfig(true) lggr := logger.Test(t) - ethKeyStore := cltest.NewKeyStore(t, db, logCfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) ccfg := evmtest.NewChainScopedConfig(t, cfg) @@ -101,9 +100,8 @@ func Test_EthResender_alertUnconfirmed(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - logCfg := pgtest.NewQConfig(true) lggr, o := logger.TestObserved(t, zapcore.DebugLevel) - ethKeyStore := cltest.NewKeyStore(t, db, logCfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) // Set this to the smallest non-zero value possible for the attempt to be eligible for resend delay := commonconfig.MustNewDuration(1 * time.Nanosecond) @@ -149,7 +147,7 @@ func Test_EthResender_Start(t *testing.T) { c.EVM[0].RPCDefaultBatchSize = ptr[uint32](1) }) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ccfg := evmtest.NewChainScopedConfig(t, cfg) _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.Test(t) diff --git a/core/chains/evm/txmgr/tracker_test.go b/core/chains/evm/txmgr/tracker_test.go index eefd89c69eb..a0503253591 100644 --- a/core/chains/evm/txmgr/tracker_test.go +++ b/core/chains/evm/txmgr/tracker_test.go @@ -22,9 +22,8 @@ const waitTime = 5 * time.Millisecond func newTestEvmTrackerSetup(t *testing.T) (*txmgr.Tracker, txmgr.TestEvmTxStore, keystore.Eth, []common.Address) { db := pgtest.NewSqlxDB(t) - cfg := newTestChainScopedConfig(t) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() chainID := big.NewInt(0) var enabledAddresses []common.Address _, addr1 := cltest.MustInsertRandomKey(t, ethKeyStore, *ubig.NewI(chainID.Int64())) diff --git a/core/chains/evm/txmgr/txmgr_test.go b/core/chains/evm/txmgr/txmgr_test.go index 1774a2ad86e..691b83f8e4c 100644 --- a/core/chains/evm/txmgr/txmgr_test.go +++ b/core/chains/evm/txmgr/txmgr_test.go @@ -92,7 +92,7 @@ func TestTxm_SendNativeToken_DoesNotSendToZero(t *testing.T) { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - keyStore := cltest.NewKeyStore(t, db, dbConfig).Eth() + keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.Test(t), ethClient, config, evmConfig.GasEstimator()) txm, err := makeTestEvmTxm(t, db, ethClient, estimator, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), keyStore) @@ -107,9 +107,8 @@ func TestTxm_CreateTransaction(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + kst := cltest.NewKeyStore(t, db) _, fromAddress := cltest.MustInsertRandomKey(t, kst.Eth()) toAddress := testutils.NewAddress() @@ -387,9 +386,8 @@ func newMockTxStrategy(t *testing.T) *commontxmmocks.TxStrategy { func TestTxm_CreateTransaction_OutOfEth(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - etKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + etKeyStore := cltest.NewKeyStore(t, db).Eth() thisKey, _ := cltest.RandomKey{Nonce: 1}.MustInsert(t, etKeyStore) otherKey, _ := cltest.RandomKey{Nonce: 1}.MustInsert(t, etKeyStore) @@ -528,7 +526,7 @@ func TestTxm_Reset(t *testing.T) { db := pgtest.NewSqlxDB(t) gcfg := configtest.NewTestGeneralConfig(t) cfg := evmtest.NewChainScopedConfig(t, gcfg) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + kst := cltest.NewKeyStore(t, db) _, addr := cltest.RandomKey{}.MustInsert(t, kst.Eth()) _, addr2 := cltest.RandomKey{}.MustInsert(t, kst.Eth()) diff --git a/core/chains/evm/types/models_test.go b/core/chains/evm/types/models_test.go index 38dbfa76a0a..ef355a01bda 100644 --- a/core/chains/evm/types/models_test.go +++ b/core/chains/evm/types/models_test.go @@ -25,7 +25,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" ) @@ -93,8 +92,7 @@ func TestEthTx_GetID(t *testing.T) { func TestEthTxAttempt_GetSignedTx(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) tx := cltest.NewLegacyTransaction(uint64(42), testutils.NewAddress(), big.NewInt(142), 242, big.NewInt(342), []byte{1, 2, 3}) diff --git a/core/cmd/cosmos_keys_commands_test.go b/core/cmd/cosmos_keys_commands_test.go index 16609daadc6..7c3b4ed19f7 100644 --- a/core/cmd/cosmos_keys_commands_test.go +++ b/core/cmd/cosmos_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "flag" "fmt" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -58,18 +60,20 @@ func TestShell_CosmosKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().Cosmos() cleanup := func() { + ctx := context.Background() keys, err := ks.GetAll() require.NoError(t, err) for _, key := range keys { - require.NoError(t, utils.JustError(ks.Delete(key.ID()))) + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) } requireCosmosKeyCount(t, app, 0) } t.Run("ListCosmosKeys", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().Cosmos().Create() + key, err := app.GetKeyStore().Cosmos().Create(ctx) require.NoError(t, err) requireCosmosKeyCount(t, app, 1) assert.Nil(t, cmd.NewCosmosKeysClient(client).ListKeys(cltest.EmptyCLIContext())) @@ -90,8 +94,9 @@ func TestShell_CosmosKeys(t *testing.T) { t.Run("DeleteCosmosKey", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().Cosmos().Create() + key, err := app.GetKeyStore().Cosmos().Create(ctx) require.NoError(t, err) requireCosmosKeyCount(t, app, 1) set := flag.NewFlagSet("test", 0) @@ -110,9 +115,10 @@ func TestShell_CosmosKeys(t *testing.T) { t.Run("ImportExportCosmosKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(t) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().Cosmos().Create() + _, err := app.GetKeyStore().Cosmos().Create(ctx) require.NoError(t, err) keys := requireCosmosKeyCount(t, app, 1) @@ -146,7 +152,7 @@ func TestShell_CosmosKeys(t *testing.T) { require.NoError(t, tclient.ExportKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().Cosmos().Delete(key.ID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().Cosmos().Delete(ctx, key.ID()))) requireCosmosKeyCount(t, app, 0) set = flag.NewFlagSet("test Cosmos import", 0) diff --git a/core/cmd/cosmos_transaction_commands_test.go b/core/cmd/cosmos_transaction_commands_test.go index 5b5454eed44..c3e6a048103 100644 --- a/core/cmd/cosmos_transaction_commands_test.go +++ b/core/cmd/cosmos_transaction_commands_test.go @@ -40,6 +40,7 @@ func TestMain(m *testing.M) { } func TestShell_SendCosmosCoins(t *testing.T) { + ctx := testutils.Context(t) // TODO(BCI-978): cleanup once SetupLocalCosmosNode is updated chainID := cosmostest.RandomChainID() cosmosChain := coscfg.Chain{} @@ -57,7 +58,7 @@ func TestShell_SendCosmosCoins(t *testing.T) { from := accounts[0] to := accounts[1] - require.NoError(t, app.GetKeyStore().Cosmos().Add(cosmoskey.Raw(from.PrivateKey.Bytes()).Key())) + require.NoError(t, app.GetKeyStore().Cosmos().Add(ctx, cosmoskey.Raw(from.PrivateKey.Bytes()).Key())) chain, err := app.GetRelayers().LegacyCosmosChains().Get(chainID) require.NoError(t, err) diff --git a/core/cmd/csa_keys_commands_test.go b/core/cmd/csa_keys_commands_test.go index a181922979a..86e1b7d544f 100644 --- a/core/cmd/csa_keys_commands_test.go +++ b/core/cmd/csa_keys_commands_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -53,9 +54,10 @@ func TestCSAKeyPresenter_RenderTable(t *testing.T) { func TestShell_ListCSAKeys(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) - key, err := app.GetKeyStore().CSA().Create() + key, err := app.GetKeyStore().CSA().Create(ctx) require.NoError(t, err) requireCSAKeyCount(t, app, 1) @@ -85,11 +87,12 @@ func TestShell_ImportExportCsaKey(t *testing.T) { t.Parallel() defer deleteKeyExportFile(t) + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().CSA().Create() + _, err := app.GetKeyStore().CSA().Create(ctx) require.NoError(t, err) keys := requireCSAKeyCount(t, app, 1) @@ -122,7 +125,7 @@ func TestShell_ImportExportCsaKey(t *testing.T) { require.NoError(t, client.ExportCSAKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().CSA().Delete(key.ID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().CSA().Delete(ctx, key.ID()))) requireCSAKeyCount(t, app, 0) //Import test diff --git a/core/cmd/dkgencrypt_keys_commands_test.go b/core/cmd/dkgencrypt_keys_commands_test.go index b4c6d6f6e91..7b0de4f7774 100644 --- a/core/cmd/dkgencrypt_keys_commands_test.go +++ b/core/cmd/dkgencrypt_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "flag" "fmt" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -58,18 +60,20 @@ func TestShell_DKGEncryptKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().DKGEncrypt() cleanup := func() { + ctx := context.Background() keys, err := ks.GetAll() assert.NoError(t, err) for _, key := range keys { - assert.NoError(t, utils.JustError(ks.Delete(key.ID()))) + assert.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) } requireDKGEncryptKeyCount(t, app, 0) } t.Run("ListDKGEncryptKeys", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().DKGEncrypt().Create() + key, err := app.GetKeyStore().DKGEncrypt().Create(ctx) assert.NoError(tt, err) requireDKGEncryptKeyCount(t, app, 1) assert.Nil(t, cmd.NewDKGEncryptKeysClient(client).ListKeys(cltest.EmptyCLIContext())) @@ -89,8 +93,9 @@ func TestShell_DKGEncryptKeys(t *testing.T) { t.Run("DeleteDKGEncryptKey", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().DKGEncrypt().Create() + key, err := app.GetKeyStore().DKGEncrypt().Create(ctx) assert.NoError(tt, err) requireDKGEncryptKeyCount(tt, app, 1) set := flag.NewFlagSet("test", 0) @@ -110,9 +115,10 @@ func TestShell_DKGEncryptKeys(t *testing.T) { t.Run("ImportExportDKGEncryptKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(tt) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().DKGEncrypt().Create() + _, err := app.GetKeyStore().DKGEncrypt().Create(ctx) require.NoError(tt, err) keys := requireDKGEncryptKeyCount(tt, app, 1) @@ -146,7 +152,7 @@ func TestShell_DKGEncryptKeys(t *testing.T) { require.NoError(tt, cmd.NewDKGEncryptKeysClient(client).ExportKey(c)) require.NoError(tt, utils.JustError(os.Stat(keyName))) - require.NoError(tt, utils.JustError(app.GetKeyStore().DKGEncrypt().Delete(key.ID()))) + require.NoError(tt, utils.JustError(app.GetKeyStore().DKGEncrypt().Delete(ctx, key.ID()))) requireDKGEncryptKeyCount(tt, app, 0) //Import test diff --git a/core/cmd/dkgsign_keys_commands_test.go b/core/cmd/dkgsign_keys_commands_test.go index 717f988b328..777e8a0a3c3 100644 --- a/core/cmd/dkgsign_keys_commands_test.go +++ b/core/cmd/dkgsign_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "flag" "fmt" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -58,18 +60,20 @@ func TestShell_DKGSignKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().DKGSign() cleanup := func() { + ctx := context.Background() keys, err := ks.GetAll() assert.NoError(t, err) for _, key := range keys { - assert.NoError(t, utils.JustError(ks.Delete(key.ID()))) + assert.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) } requireDKGSignKeyCount(t, app, 0) } t.Run("ListDKGSignKeys", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().DKGSign().Create() + key, err := app.GetKeyStore().DKGSign().Create(ctx) assert.NoError(tt, err) requireDKGSignKeyCount(t, app, 1) assert.Nil(t, cmd.NewDKGSignKeysClient(client).ListKeys(cltest.EmptyCLIContext())) @@ -89,8 +93,9 @@ func TestShell_DKGSignKeys(t *testing.T) { t.Run("DeleteDKGSignKey", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().DKGSign().Create() + key, err := app.GetKeyStore().DKGSign().Create(ctx) assert.NoError(tt, err) requireDKGSignKeyCount(tt, app, 1) set := flag.NewFlagSet("test", 0) @@ -109,9 +114,10 @@ func TestShell_DKGSignKeys(t *testing.T) { t.Run("ImportExportDKGSignKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(tt) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().DKGSign().Create() + _, err := app.GetKeyStore().DKGSign().Create(ctx) require.NoError(tt, err) keys := requireDKGSignKeyCount(tt, app, 1) @@ -145,7 +151,7 @@ func TestShell_DKGSignKeys(t *testing.T) { require.NoError(tt, cmd.NewDKGSignKeysClient(client).ExportKey(c)) require.NoError(tt, utils.JustError(os.Stat(keyName))) - require.NoError(tt, utils.JustError(app.GetKeyStore().DKGSign().Delete(key.ID()))) + require.NoError(tt, utils.JustError(app.GetKeyStore().DKGSign().Delete(ctx, key.ID()))) requireDKGSignKeyCount(tt, app, 0) set = flag.NewFlagSet("test DKGSign import", 0) diff --git a/core/cmd/key_store_authenticator.go b/core/cmd/key_store_authenticator.go index 0707aa5087d..6ad4b0ef2ba 100644 --- a/core/cmd/key_store_authenticator.go +++ b/core/cmd/key_store_authenticator.go @@ -1,6 +1,7 @@ package cmd import ( + "context" "fmt" "strings" @@ -20,8 +21,8 @@ type keystorePassword interface { Keystore() string } -func (auth TerminalKeyStoreAuthenticator) authenticate(keyStore keystore.Master, password keystorePassword) error { - isEmpty, err := keyStore.IsEmpty() +func (auth TerminalKeyStoreAuthenticator) authenticate(ctx context.Context, keyStore keystore.Master, password keystorePassword) error { + isEmpty, err := keyStore.IsEmpty(ctx) if err != nil { return errors.Wrap(err, "error determining if keystore is empty") } @@ -34,7 +35,7 @@ func (auth TerminalKeyStoreAuthenticator) authenticate(keyStore keystore.Master, if err = auth.validatePasswordStrength(pw); err != nil && isEmpty { return err } - return keyStore.Unlock(pw) + return keyStore.Unlock(ctx, pw) } interactive := auth.Prompter.IsTerminal() if !interactive { @@ -47,7 +48,7 @@ func (auth TerminalKeyStoreAuthenticator) authenticate(keyStore keystore.Master, if err != nil { return err } - return keyStore.Unlock(pw) + return keyStore.Unlock(ctx, pw) } func (auth TerminalKeyStoreAuthenticator) validatePasswordStrength(password string) error { diff --git a/core/cmd/ocr2_keys_commands_test.go b/core/cmd/ocr2_keys_commands_test.go index eff44685612..b0c62f01aa5 100644 --- a/core/cmd/ocr2_keys_commands_test.go +++ b/core/cmd/ocr2_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "encoding/hex" "flag" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -71,19 +73,21 @@ func TestShell_OCR2Keys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().OCR2() cleanup := func() { + ctx := context.Background() keys, err := app.GetKeyStore().OCR2().GetAll() require.NoError(t, err) for _, key := range keys { - require.NoError(t, ks.Delete(key.ID())) + require.NoError(t, ks.Delete(ctx, key.ID())) } requireOCR2KeyCount(t, app, 0) } t.Run("ListOCR2KeyBundles", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().OCR2().Create("evm") + key, err := app.GetKeyStore().OCR2().Create(ctx, "evm") require.NoError(t, err) requireOCR2KeyCount(t, app, 1) assert.Nil(t, client.ListOCR2KeyBundles(cltest.EmptyCLIContext())) @@ -113,9 +117,10 @@ func TestShell_OCR2Keys(t *testing.T) { t.Run("DeleteOCR2KeyBundle", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().OCR2().Create("evm") + key, err := app.GetKeyStore().OCR2().Create(ctx, "evm") require.NoError(t, err) requireOCR2KeyCount(t, app, 1) set := flag.NewFlagSet("test", 0) @@ -136,9 +141,10 @@ func TestShell_OCR2Keys(t *testing.T) { t.Run("ImportExportOCR2Key", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(t) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - err := app.KeyStore.OCR2().Add(cltest.DefaultOCR2Key) + err := app.KeyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key) require.NoError(t, err) keys := requireOCR2KeyCount(t, app, 1) @@ -171,7 +177,7 @@ func TestShell_OCR2Keys(t *testing.T) { require.NoError(t, client.ExportOCR2Key(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, app.GetKeyStore().OCR2().Delete(key.ID())) + require.NoError(t, app.GetKeyStore().OCR2().Delete(ctx, key.ID())) requireOCR2KeyCount(t, app, 0) set = flag.NewFlagSet("test OCR2 import", 0) diff --git a/core/cmd/ocr2vrf_configure_commands.go b/core/cmd/ocr2vrf_configure_commands.go index 1f9e3f0bc98..7f5b0321480 100644 --- a/core/cmd/ocr2vrf_configure_commands.go +++ b/core/cmd/ocr2vrf_configure_commands.go @@ -352,7 +352,7 @@ func (s *Shell) authorizeForwarder(c *cli.Context, db *sqlx.DB, chainID int64, e } func setupKeystore(ctx context.Context, cli *Shell, app chainlink.Application, keyStore keystore.Master) error { - if err := cli.KeyStoreAuthenticator.authenticate(keyStore, cli.Config.Password()); err != nil { + if err := cli.KeyStoreAuthenticator.authenticate(ctx, keyStore, cli.Config.Password()); err != nil { return errors.Wrap(err, "error authenticating keystore") } @@ -382,19 +382,19 @@ func setupKeystore(ctx context.Context, cli *Shell, app chainlink.Application, k enabledChains = append(enabledChains, chaintype.StarkNet) } - if err := keyStore.OCR2().EnsureKeys(enabledChains...); err != nil { + if err := keyStore.OCR2().EnsureKeys(ctx, enabledChains...); err != nil { return errors.Wrap(err, "failed to ensure ocr key") } - if err := keyStore.DKGSign().EnsureKey(); err != nil { + if err := keyStore.DKGSign().EnsureKey(ctx); err != nil { return errors.Wrap(err, "failed to ensure dkgsign key") } - if err := keyStore.DKGEncrypt().EnsureKey(); err != nil { + if err := keyStore.DKGEncrypt().EnsureKey(ctx); err != nil { return errors.Wrap(err, "failed to ensure dkgencrypt key") } - if err := keyStore.P2P().EnsureKey(); err != nil { + if err := keyStore.P2P().EnsureKey(ctx); err != nil { return errors.Wrap(err, "failed to ensure p2p key") } diff --git a/core/cmd/ocr_keys_commands_test.go b/core/cmd/ocr_keys_commands_test.go index f5da3294903..42d7451edbe 100644 --- a/core/cmd/ocr_keys_commands_test.go +++ b/core/cmd/ocr_keys_commands_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -65,11 +66,12 @@ func TestOCRKeyBundlePresenter_RenderTable(t *testing.T) { func TestShell_ListOCRKeyBundles(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().OCR().Create() + key, err := app.GetKeyStore().OCR().Create(ctx) require.NoError(t, err) requireOCRKeyCount(t, app, 1) @@ -101,11 +103,12 @@ func TestShell_CreateOCRKeyBundle(t *testing.T) { func TestShell_DeleteOCRKeyBundle(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().OCR().Create() + key, err := app.GetKeyStore().OCR().Create(ctx) require.NoError(t, err) requireOCRKeyCount(t, app, 1) @@ -128,11 +131,12 @@ func TestShell_DeleteOCRKeyBundle(t *testing.T) { func TestShell_ImportExportOCRKey(t *testing.T) { defer deleteKeyExportFile(t) + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) client, _ := app.NewShellAndRenderer() - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) keys := requireOCRKeyCount(t, app, 1) key := keys[0] @@ -164,7 +168,7 @@ func TestShell_ImportExportOCRKey(t *testing.T) { require.NoError(t, client.ExportOCRKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().OCR().Delete(key.ID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().OCR().Delete(ctx, key.ID()))) requireOCRKeyCount(t, app, 0) set = flag.NewFlagSet("test OCR import", 0) diff --git a/core/cmd/p2p_keys_commands_test.go b/core/cmd/p2p_keys_commands_test.go index 87269e02711..12d22e7c16b 100644 --- a/core/cmd/p2p_keys_commands_test.go +++ b/core/cmd/p2p_keys_commands_test.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -61,9 +62,10 @@ func TestP2PKeyPresenter_RenderTable(t *testing.T) { func TestShell_ListP2PKeys(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) - key, err := app.GetKeyStore().P2P().Create() + key, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) requireP2PKeyCount(t, app, 1) @@ -92,11 +94,12 @@ func TestShell_CreateP2PKey(t *testing.T) { func TestShell_DeleteP2PKey(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, nil) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().P2P().Create() + key, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) requireP2PKeyCount(t, app, 1) @@ -118,12 +121,13 @@ func TestShell_DeleteP2PKey(t *testing.T) { func TestShell_ImportExportP2PKeyBundle(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) defer deleteKeyExportFile(t) app := startNewApplicationV2(t, nil) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().P2P().Create() + _, err := app.GetKeyStore().P2P().Create(ctx) require.NoError(t, err) keys := requireP2PKeyCount(t, app, 1) @@ -156,7 +160,7 @@ func TestShell_ImportExportP2PKeyBundle(t *testing.T) { require.NoError(t, client.ExportP2PKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().P2P().Delete(key.PeerID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().P2P().Delete(ctx, key.PeerID()))) requireP2PKeyCount(t, app, 0) set = flag.NewFlagSet("test P2P import", 0) diff --git a/core/cmd/shell.go b/core/cmd/shell.go index de84ed401a6..bc58c5cab6d 100644 --- a/core/cmd/shell.go +++ b/core/cmd/shell.go @@ -154,7 +154,7 @@ func (n ChainlinkAppFactory) NewApplication(ctx context.Context, cfg chainlink.G return nil, err } - keyStore := keystore.New(sqlxDB, utils.GetScryptParams(cfg), appLggr, cfg.Database()) + keyStore := keystore.New(db, utils.GetScryptParams(cfg), appLggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), appLggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(appLggr, cfg.Tracing()) diff --git a/core/cmd/shell_local.go b/core/cmd/shell_local.go index 0639d5a21df..66ceafa5cb2 100644 --- a/core/cmd/shell_local.go +++ b/core/cmd/shell_local.go @@ -364,7 +364,7 @@ func (s *Shell) runNode(c *cli.Context) error { // Local shell initialization always uses local auth users table for admin auth authProviderORM := app.BasicAdminUsersORM() keyStore := app.GetKeyStore() - err = s.KeyStoreAuthenticator.authenticate(keyStore, s.Config.Password()) + err = s.KeyStoreAuthenticator.authenticate(rootCtx, keyStore, s.Config.Password()) if err != nil { return errors.Wrap(err, "error authenticating keystore") } @@ -390,7 +390,7 @@ func (s *Shell) runNode(c *cli.Context) error { } if s.Config.OCR().Enabled() { - err2 := app.GetKeyStore().OCR().EnsureKey() + err2 := app.GetKeyStore().OCR().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure ocr key") } @@ -409,37 +409,37 @@ func (s *Shell) runNode(c *cli.Context) error { if s.Config.StarkNetEnabled() { enabledChains = append(enabledChains, chaintype.StarkNet) } - err2 := app.GetKeyStore().OCR2().EnsureKeys(enabledChains...) + err2 := app.GetKeyStore().OCR2().EnsureKeys(rootCtx, enabledChains...) if err2 != nil { return errors.Wrap(err2, "failed to ensure ocr key") } } if s.Config.P2P().Enabled() { - err2 := app.GetKeyStore().P2P().EnsureKey() + err2 := app.GetKeyStore().P2P().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure p2p key") } } if s.Config.CosmosEnabled() { - err2 := app.GetKeyStore().Cosmos().EnsureKey() + err2 := app.GetKeyStore().Cosmos().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure cosmos key") } } if s.Config.SolanaEnabled() { - err2 := app.GetKeyStore().Solana().EnsureKey() + err2 := app.GetKeyStore().Solana().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure solana key") } } if s.Config.StarkNetEnabled() { - err2 := app.GetKeyStore().StarkNet().EnsureKey() + err2 := app.GetKeyStore().StarkNet().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure starknet key") } } - err2 := app.GetKeyStore().CSA().EnsureKey() + err2 := app.GetKeyStore().CSA().EnsureKey(rootCtx) if err2 != nil { return errors.Wrap(err2, "failed to ensure CSA key") } @@ -621,7 +621,7 @@ func (s *Shell) RebroadcastTransactions(c *cli.Context) (err error) { return s.errorOut(fmt.Errorf("error validating configuration: %+v", err)) } - err = keyStore.Unlock(s.Config.Password().Keystore()) + err = keyStore.Unlock(ctx, s.Config.Password().Keystore()) if err != nil { return s.errorOut(errors.Wrap(err, "error authenticating keystore")) } diff --git a/core/cmd/shell_local_test.go b/core/cmd/shell_local_test.go index 6ac401e906c..0db99d1a57a 100644 --- a/core/cmd/shell_local_test.go +++ b/core/cmd/shell_local_test.go @@ -80,7 +80,7 @@ func TestShell_RunNodeWithPasswords(t *testing.T) { c.Insecure.OCRDevelopmentMode = nil }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) authProviderORM := localauth.NewORM(db, time.Minute, logger.TestLogger(t), audit.NoopLogger) lggr := logger.TestLogger(t) @@ -181,7 +181,7 @@ func TestShell_RunNodeWithAPICredentialsFile(t *testing.T) { // create/run with a new admin user pgtest.MustExec(t, db, "DELETE FROM users;") - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) _, err := keyStore.Eth().Create(testutils.Context(t), &cltest.FixtureChainID) require.NoError(t, err) @@ -290,7 +290,7 @@ func TestShell_RebroadcastTransactions_Txm(t *testing.T) { // seems to be needed for config validate c.Insecure.OCRDevelopmentMode = nil }) - keyStore := cltest.NewKeyStore(t, sqlxDB, config.Database()) + keyStore := cltest.NewKeyStore(t, sqlxDB) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) txStore := cltest.NewTestTxStore(t, sqlxDB) @@ -370,7 +370,7 @@ func TestShell_RebroadcastTransactions_OutsideRange_Txm(t *testing.T) { c.Insecure.OCRDevelopmentMode = nil }) - keyStore := cltest.NewKeyStore(t, sqlxDB, config.Database()) + keyStore := cltest.NewKeyStore(t, sqlxDB) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) @@ -446,7 +446,7 @@ func TestShell_RebroadcastTransactions_AddressCheck(t *testing.T) { c.Insecure.OCRDevelopmentMode = nil }) - keyStore := cltest.NewKeyStore(t, sqlxDB, config.Database()) + keyStore := cltest.NewKeyStore(t, sqlxDB) _, fromAddress := cltest.MustInsertRandomKey(t, keyStore.Eth()) diff --git a/core/cmd/shell_remote_test.go b/core/cmd/shell_remote_test.go index 0d8d0b7b459..a8c054cd9be 100644 --- a/core/cmd/shell_remote_test.go +++ b/core/cmd/shell_remote_test.go @@ -565,6 +565,7 @@ func TestShell_ConfigV2(t *testing.T) { func TestShell_RunOCRJob_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) app := startNewApplicationV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].Enabled = ptr(true) c.OCR.Enabled = ptr(true) @@ -577,7 +578,7 @@ func TestShell_RunOCRJob_HappyPath(t *testing.T) { }) client, _ := app.NewShellAndRenderer() - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) _, bridge2 := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) diff --git a/core/cmd/solana_keys_commands_test.go b/core/cmd/solana_keys_commands_test.go index d58c3657019..897031877c1 100644 --- a/core/cmd/solana_keys_commands_test.go +++ b/core/cmd/solana_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "flag" "fmt" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -58,18 +60,20 @@ func TestShell_SolanaKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().Solana() cleanup := func() { + ctx := context.Background() keys, err := ks.GetAll() require.NoError(t, err) for _, key := range keys { - require.NoError(t, utils.JustError(ks.Delete(key.ID()))) + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) } requireSolanaKeyCount(t, app, 0) } t.Run("ListSolanaKeys", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().Solana().Create() + key, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) requireSolanaKeyCount(t, app, 1) assert.Nil(t, cmd.NewSolanaKeysClient(client).ListKeys(cltest.EmptyCLIContext())) @@ -90,8 +94,9 @@ func TestShell_SolanaKeys(t *testing.T) { t.Run("DeleteSolanaKey", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().Solana().Create() + key, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) requireSolanaKeyCount(t, app, 1) set := flag.NewFlagSet("test", 0) @@ -111,9 +116,10 @@ func TestShell_SolanaKeys(t *testing.T) { t.Run("ImportExportSolanaKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(t) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().Solana().Create() + _, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) keys := requireSolanaKeyCount(t, app, 1) @@ -146,7 +152,7 @@ func TestShell_SolanaKeys(t *testing.T) { require.NoError(t, cmd.NewSolanaKeysClient(client).ExportKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().Solana().Delete(key.ID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().Solana().Delete(ctx, key.ID()))) requireSolanaKeyCount(t, app, 0) set = flag.NewFlagSet("test Solana import", 0) diff --git a/core/cmd/solana_transaction_commands_test.go b/core/cmd/solana_transaction_commands_test.go index b190caec51b..c26bd89ab94 100644 --- a/core/cmd/solana_transaction_commands_test.go +++ b/core/cmd/solana_transaction_commands_test.go @@ -19,11 +19,13 @@ import ( "github.com/smartcontractkit/chainlink-solana/pkg/solana" solanaClient "github.com/smartcontractkit/chainlink-solana/pkg/solana/client" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/cmd" ) func TestShell_SolanaSendSol(t *testing.T) { + ctx := testutils.Context(t) chainID := "localnet" url := solanaClient.SetupLocalSolNode(t) node := solcfg.Node{ @@ -36,7 +38,7 @@ func TestShell_SolanaSendSol(t *testing.T) { Enabled: ptr(true), } app := solanaStartNewApplication(t, &cfg) - from, err := app.GetKeyStore().Solana().Create() + from, err := app.GetKeyStore().Solana().Create(ctx) require.NoError(t, err) to, err := solanago.NewRandomPrivateKey() require.NoError(t, err) diff --git a/core/cmd/starknet_keys_commands_test.go b/core/cmd/starknet_keys_commands_test.go index 0cf0065129d..5823a80b46d 100644 --- a/core/cmd/starknet_keys_commands_test.go +++ b/core/cmd/starknet_keys_commands_test.go @@ -2,6 +2,7 @@ package cmd_test import ( "bytes" + "context" "flag" "fmt" "os" @@ -14,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/cmd" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" @@ -57,18 +59,20 @@ func TestShell_StarkNetKeys(t *testing.T) { app := startNewApplicationV2(t, nil) ks := app.GetKeyStore().StarkNet() cleanup := func() { + ctx := context.Background() keys, err := ks.GetAll() require.NoError(t, err) for _, key := range keys { - require.NoError(t, utils.JustError(ks.Delete(key.ID()))) + require.NoError(t, utils.JustError(ks.Delete(ctx, key.ID()))) } requireStarkNetKeyCount(t, app, 0) } t.Run("ListStarkNetKeys", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, r := app.NewShellAndRenderer() - key, err := app.GetKeyStore().StarkNet().Create() + key, err := app.GetKeyStore().StarkNet().Create(ctx) require.NoError(t, err) requireStarkNetKeyCount(t, app, 1) assert.Nil(t, cmd.NewStarkNetKeysClient(client).ListKeys(cltest.EmptyCLIContext())) @@ -89,8 +93,9 @@ func TestShell_StarkNetKeys(t *testing.T) { t.Run("DeleteStarkNetKey", func(tt *testing.T) { defer cleanup() + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - key, err := app.GetKeyStore().StarkNet().Create() + key, err := app.GetKeyStore().StarkNet().Create(ctx) require.NoError(t, err) requireStarkNetKeyCount(t, app, 1) set := flag.NewFlagSet("test", 0) @@ -110,9 +115,10 @@ func TestShell_StarkNetKeys(t *testing.T) { t.Run("ImportExportStarkNetKey", func(tt *testing.T) { defer cleanup() defer deleteKeyExportFile(t) + ctx := testutils.Context(t) client, _ := app.NewShellAndRenderer() - _, err := app.GetKeyStore().StarkNet().Create() + _, err := app.GetKeyStore().StarkNet().Create(ctx) require.NoError(t, err) keys := requireStarkNetKeyCount(t, app, 1) @@ -145,7 +151,7 @@ func TestShell_StarkNetKeys(t *testing.T) { require.NoError(t, cmd.NewStarkNetKeysClient(client).ExportKey(c)) require.NoError(t, utils.JustError(os.Stat(keyName))) - require.NoError(t, utils.JustError(app.GetKeyStore().StarkNet().Delete(key.ID()))) + require.NoError(t, utils.JustError(app.GetKeyStore().StarkNet().Delete(ctx, key.ID()))) requireStarkNetKeyCount(t, app, 0) set = flag.NewFlagSet("test StarkNet import", 0) diff --git a/core/internal/cltest/cltest.go b/core/internal/cltest/cltest.go index ba182d60515..8123439dafb 100644 --- a/core/internal/cltest/cltest.go +++ b/core/internal/cltest/cltest.go @@ -38,6 +38,7 @@ import ( ocrtypes "github.com/smartcontractkit/libocr/offchainreporting/types" "github.com/smartcontractkit/chainlink-common/pkg/loop" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox" "github.com/smartcontractkit/chainlink/v2/common/client" @@ -263,18 +264,19 @@ func NewApplicationWithConfigAndKey(t testing.TB, c chainlink.GeneralConfig, fla } func setKeys(t testing.TB, app *TestApplication, flagsAndDeps ...interface{}) (chainID ubig.Big) { - require.NoError(t, app.KeyStore.Unlock(Password)) + ctx := testutils.Context(t) + require.NoError(t, app.KeyStore.Unlock(ctx, Password)) for _, dep := range flagsAndDeps { switch v := dep.(type) { case ethkey.KeyV2: app.Keys = append(app.Keys, v) case p2pkey.KeyV2: - require.NoError(t, app.GetKeyStore().P2P().Add(v)) + require.NoError(t, app.GetKeyStore().P2P().Add(ctx, v)) case csakey.KeyV2: - require.NoError(t, app.GetKeyStore().CSA().Add(v)) + require.NoError(t, app.GetKeyStore().CSA().Add(ctx, v)) case ocr2key.KeyBundle: - require.NoError(t, app.GetKeyStore().OCR2().Add(v)) + require.NoError(t, app.GetKeyStore().OCR2().Add(ctx, v)) } } @@ -341,7 +343,7 @@ func NewApplicationWithConfig(t testing.TB, cfg chainlink.GeneralConfig, flagsAn } } - keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) + keyStore := keystore.NewInMemory(db, utils.FastScryptParams, lggr) mailMon := mailbox.NewMonitor(cfg.AppID().String(), lggr.Named("Mailbox")) loopRegistry := plugins.NewLoopRegistry(lggr, nil) @@ -534,7 +536,7 @@ func NewEthMocksWithTransactionsOnBlocksAssertions(t testing.TB) *evmclimocks.Cl func (ta *TestApplication) Start(ctx context.Context) error { ta.t.Helper() ta.Started = true - err := ta.ChainlinkApplication.KeyStore.Unlock(Password) + err := ta.ChainlinkApplication.KeyStore.Unlock(ctx, Password) if err != nil { return err } @@ -576,7 +578,7 @@ func (ta *TestApplication) MustSeedNewSession(email string) (id string) { // ImportKey adds private key to the application keystore and database func (ta *TestApplication) Import(ctx context.Context, content string) { - require.NoError(ta.t, ta.KeyStore.Unlock(Password)) + require.NoError(ta.t, ta.KeyStore.Unlock(ctx, Password)) _, err := ta.KeyStore.Eth().Import(ctx, []byte(content), Password, &FixtureChainID) require.NoError(ta.t, err) } @@ -661,9 +663,10 @@ func (ta *TestApplication) NewAuthenticatingShell(prompter cmd.Prompter) *cmd.Sh } // NewKeyStore returns a new, unlocked keystore -func NewKeyStore(t testing.TB, db *sqlx.DB, cfg pg.QConfig) keystore.Master { - keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger.TestLogger(t), cfg) - require.NoError(t, keystore.Unlock(Password)) +func NewKeyStore(t testing.TB, ds sqlutil.DataSource) keystore.Master { + ctx := testutils.Context(t) + keystore := keystore.NewInMemory(ds, utils.FastScryptParams, logger.TestLogger(t)) + require.NoError(t, keystore.Unlock(ctx, Password)) return keystore } @@ -1511,8 +1514,8 @@ func EventuallyExpectationsMet(t *testing.T, mock testifyExpectationsAsserter, t } } -func AssertCount(t *testing.T, db *sqlx.DB, tableName string, expected int64) { - testutils.AssertCount(t, db, tableName, expected) +func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected int64) { + testutils.AssertCount(t, ds, tableName, expected) } func WaitForCount(t *testing.T, db *sqlx.DB, tableName string, want int64) { @@ -1560,8 +1563,8 @@ func NewTestChainScopedConfig(t testing.TB) evmconfig.ChainScopedConfig { return evmtest.NewChainScopedConfig(t, cfg) } -func NewTestTxStore(t *testing.T, db *sqlx.DB) txmgr.TestEvmTxStore { - return txmgr.NewTxStore(db, logger.TestLogger(t)) +func NewTestTxStore(t *testing.T, ds sqlutil.DataSource) txmgr.TestEvmTxStore { + return txmgr.NewTxStore(ds, logger.TestLogger(t)) } // ClearDBTables deletes all rows from the given tables diff --git a/core/internal/cltest/job_factories.go b/core/internal/cltest/job_factories.go index 2b527fbc29c..d78440838b2 100644 --- a/core/internal/cltest/job_factories.go +++ b/core/internal/cltest/job_factories.go @@ -62,7 +62,7 @@ func MustInsertWebhookSpec(t *testing.T, db *sqlx.DB) (job.Job, job.WebhookSpec) func getORMs(t *testing.T, db *sqlx.DB) (jobORM job.ORM, pipelineORM pipeline.ORM) { config := configtest.NewTestGeneralConfig(t) - keyStore := NewKeyStore(t, db, config.Database()) + keyStore := NewKeyStore(t, db) lggr := logger.TestLogger(t) pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) diff --git a/core/internal/features/features_test.go b/core/internal/features/features_test.go index 4afad453110..516f0ae0907 100644 --- a/core/internal/features/features_test.go +++ b/core/internal/features/features_test.go @@ -681,6 +681,7 @@ func setupOCRContracts(t *testing.T) (*bind.TransactOpts, *backends.SimulatedBac func setupNode(t *testing.T, owner *bind.TransactOpts, portV2 int, b *backends.SimulatedBackend, overrides func(c *chainlink.Config, s *chainlink.Secrets), ) (*cltest.TestApplication, string, common.Address, ocrkey.KeyV2) { + ctx := testutils.Context(t) p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -719,12 +720,13 @@ func setupNode(t *testing.T, owner *bind.TransactOpts, portV2 int, require.NoError(t, err) b.Commit() - key, err := app.GetKeyStore().OCR().Create() + key, err := app.GetKeyStore().OCR().Create(ctx) require.NoError(t, err) return app, p2pKey.PeerID().Raw(), transmitter, key } func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 int, b *backends.SimulatedBackend, overrides func(c *chainlink.Config, s *chainlink.Secrets)) (*cltest.TestApplication, string, common.Address, common.Address, ocrkey.KeyV2) { + ctx := testutils.Context(t) p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -761,7 +763,7 @@ func setupForwarderEnabledNode(t *testing.T, owner *bind.TransactOpts, portV2 in require.NoError(t, err) b.Commit() - key, err := app.GetKeyStore().OCR().Create() + key, err := app.GetKeyStore().OCR().Create(ctx) require.NoError(t, err) // deploy a forwarder @@ -1241,6 +1243,7 @@ observationSource = """ func TestIntegration_BlockHistoryEstimator(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) var initialDefaultGasPrice int64 = 5_000_000_000 maxGasPrice := assets.NewWeiI(10 * initialDefaultGasPrice) @@ -1260,8 +1263,8 @@ func TestIntegration_BlockHistoryEstimator(t *testing.T) { chchNewHeads := make(chan evmtest.RawSub[*evmtypes.Head], 1) db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) - require.NoError(t, kst.Unlock(cltest.Password)) + kst := cltest.NewKeyStore(t, db) + require.NoError(t, kst.Unlock(ctx, cltest.Password)) cc := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), Client: ethClient, GeneralConfig: cfg}) diff --git a/core/internal/features/ocr2/features_ocr2_test.go b/core/internal/features/ocr2/features_ocr2_test.go index 06f57c805ec..07e0fc21d9a 100644 --- a/core/internal/features/ocr2/features_ocr2_test.go +++ b/core/internal/features/ocr2/features_ocr2_test.go @@ -111,6 +111,7 @@ func setupNodeOCR2( b *backends.SimulatedBackend, p2pV2Bootstrappers []commontypes.BootstrapperLocator, ) *ocr2Node { + ctx := testutils.Context(t) p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) // Disables ocr spec validation so we can have fast polling for the test. @@ -157,7 +158,7 @@ func setupNodeOCR2( require.NoError(t, err) b.Commit() - kb, err := app.GetKeyStore().OCR2().Create("evm") + kb, err := app.GetKeyStore().OCR2().Create(ctx, "evm") require.NoError(t, err) if useForwarder { diff --git a/core/internal/testutils/testutils.go b/core/internal/testutils/testutils.go index 9fdd50625cc..ba7e697fb62 100644 --- a/core/internal/testutils/testutils.go +++ b/core/internal/testutils/testutils.go @@ -24,15 +24,14 @@ import ( "github.com/ethereum/go-ethereum/crypto" "github.com/google/uuid" "github.com/gorilla/websocket" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/tidwall/gjson" "go.uber.org/zap/zaptest/observer" - "github.com/jmoiron/sqlx" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" // NOTE: To avoid circular dependencies, this package MUST NOT import // anything from "github.com/smartcontractkit/chainlink/v2/core" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" ) const ( @@ -419,10 +418,10 @@ func SkipShortDB(tb testing.TB) { SkipShort(tb, "DB dependency") } -func AssertCount(t *testing.T, db *sqlx.DB, tableName string, expected int64) { +func AssertCount(t *testing.T, ds sqlutil.DataSource, tableName string, expected int64) { t.Helper() var count int64 - err := db.Get(&count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) + err := ds.GetContext(Context(t), &count, fmt.Sprintf(`SELECT count(*) FROM %s;`, tableName)) require.NoError(t, err) require.Equal(t, expected, count) } diff --git a/core/scripts/vrfv2/testnet/main.go b/core/scripts/vrfv2/testnet/main.go index 34070c90d8a..88f4d9e0f73 100644 --- a/core/scripts/vrfv2/testnet/main.go +++ b/core/scripts/vrfv2/testnet/main.go @@ -44,7 +44,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -54,6 +53,7 @@ var ( ) func main() { + ctx := context.Background() e := helpers.SetupEnv(false) switch os.Args[1] { @@ -218,8 +218,8 @@ func main() { db := sqlx.MustOpen("postgres", *dbURL) lggr, _ := logger.NewLogger() - keyStore := keystore.New(db, utils.DefaultScryptParams, lggr, pg.NewQConfig(false)) - err = keyStore.Unlock(*keystorePassword) + keyStore := keystore.New(db, utils.DefaultScryptParams, lggr) + err = keyStore.Unlock(ctx, *keystorePassword) helpers.PanicErr(err) k, err := keyStore.VRF().Get(*pubKeyHex) @@ -310,8 +310,8 @@ func main() { db := sqlx.MustOpen("postgres", *dbURL) lggr, _ := logger.NewLogger() - keyStore := keystore.New(db, utils.DefaultScryptParams, lggr, pg.NewQConfig(false)) - err = keyStore.Unlock(*keystorePassword) + keyStore := keystore.New(db, utils.DefaultScryptParams, lggr) + err = keyStore.Unlock(ctx, *keystorePassword) helpers.PanicErr(err) k, err := keyStore.VRF().Get(*pubKeyHex) diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index 45ef7314bee..f42bebe952b 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -45,7 +45,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/blockhashstore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/extraargs" "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" "github.com/smartcontractkit/chainlink/v2/core/utils" @@ -56,6 +55,7 @@ var ( ) func main() { + ctx := context.Background() e := helpers.SetupEnv(false) switch os.Args[1] { @@ -196,8 +196,8 @@ func main() { db := sqlx.MustOpen("postgres", *dbURL) lggr, _ := logger.NewLogger() - keyStore := keystore.New(db, utils.DefaultScryptParams, lggr, pg.NewQConfig(false)) - err = keyStore.Unlock(*keystorePassword) + keyStore := keystore.New(db, utils.DefaultScryptParams, lggr) + err = keyStore.Unlock(ctx, *keystorePassword) helpers.PanicErr(err) k, err := keyStore.VRF().Get(*pubKeyHex) @@ -292,8 +292,8 @@ func main() { db := sqlx.MustOpen("postgres", *dbURL) lggr, _ := logger.NewLogger() - keyStore := keystore.New(db, utils.DefaultScryptParams, lggr, pg.NewQConfig(false)) - err = keyStore.Unlock(*keystorePassword) + keyStore := keystore.New(db, utils.DefaultScryptParams, lggr) + err = keyStore.Unlock(ctx, *keystorePassword) helpers.PanicErr(err) k, err := keyStore.VRF().Get(*pubKeyHex) diff --git a/core/services/blockhashstore/bhs_test.go b/core/services/blockhashstore/bhs_test.go index 75424ee8059..94e9f22ee7c 100644 --- a/core/services/blockhashstore/bhs_test.go +++ b/core/services/blockhashstore/bhs_test.go @@ -28,15 +28,15 @@ func TestStoreRotatesFromAddresses(t *testing.T) { db := pgtest.NewSqlxDB(t) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) cfg := configtest.NewTestGeneralConfig(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) - require.NoError(t, kst.Unlock(cltest.Password)) + kst := cltest.NewKeyStore(t, db) + require.NoError(t, kst.Unlock(ctx, cltest.Password)) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg, Client: ethClient}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) chain, err := legacyChains.Get(cltest.FixtureChainID.String()) require.NoError(t, err) lggr := logger.TestLogger(t) - ks := keystore.New(db, utils.FastScryptParams, lggr, cfg.Database()) - require.NoError(t, ks.Unlock("blah")) + ks := keystore.New(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, "blah")) k1, err := ks.Eth().Create(ctx, &cltest.FixtureChainID) require.NoError(t, err) k2, err := ks.Eth().Create(ctx, &cltest.FixtureChainID) diff --git a/core/services/blockhashstore/delegate_test.go b/core/services/blockhashstore/delegate_test.go index 4c37273f161..6aaeb59152a 100644 --- a/core/services/blockhashstore/delegate_test.go +++ b/core/services/blockhashstore/delegate_test.go @@ -55,7 +55,7 @@ func createTestDelegate(t *testing.T) (*blockhashstore.Delegate, *testData) { c.Feature.LogPoller = func(b bool) *bool { return &b }(true) }) db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + kst := cltest.NewKeyStore(t, db).Eth() sendingKey, _ := cltest.MustInsertRandomKey(t, kst) lp := &mocklp.LogPoller{} lp.On("RegisterFilter", mock.Anything, mock.Anything).Return(nil) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index c90811de768..38aae37c134 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -172,7 +172,7 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) lggr := logger.TestLogger(t) diff --git a/core/services/cron/cron_test.go b/core/services/cron/cron_test.go index c3ecc0957c7..b31a06a9591 100644 --- a/core/services/cron/cron_test.go +++ b/core/services/cron/cron_test.go @@ -25,7 +25,7 @@ func TestCronV2Pipeline(t *testing.T) { cfg := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) diff --git a/core/services/directrequest/delegate_test.go b/core/services/directrequest/delegate_test.go index 0235a0c4eec..08f38865bec 100644 --- a/core/services/directrequest/delegate_test.go +++ b/core/services/directrequest/delegate_test.go @@ -44,7 +44,7 @@ func TestDelegate_ServicesForSpec(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].MinIncomingConfirmations = ptr[uint32](1) }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) relayerExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, MailMon: mailMon, KeyStore: keyStore.Eth()}) @@ -85,7 +85,7 @@ func NewDirectRequestUniverseWithConfig(t *testing.T, cfg chainlink.GeneralConfi mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, LogBroadcaster: broadcaster, MailMon: mailMon, KeyStore: keyStore.Eth()}) lggr := logger.TestLogger(t) orm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) diff --git a/core/services/feeds/orm_test.go b/core/services/feeds/orm_test.go index 51a85a33a46..0cf20cf9800 100644 --- a/core/services/feeds/orm_test.go +++ b/core/services/feeds/orm_test.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/bridges" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" @@ -1647,18 +1648,19 @@ func createFeedsManager(t *testing.T, orm feeds.ORM) int64 { func createJob(t *testing.T, db *sqlx.DB, externalJobID uuid.UUID) *job.Job { t.Helper() + ctx := testutils.Context(t) var ( config = configtest.NewGeneralConfig(t, nil) - keyStore = cltest.NewKeyStore(t, db, config.Database()) + keyStore = cltest.NewKeyStore(t, db) lggr = logger.TestLogger(t) pipelineORM = pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM = bridges.NewORM(db) relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: config, KeyStore: keyStore.Eth()}) ) orm := job.NewORM(db, pipelineORM, bridgeORM, keyStore, lggr, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) defer func() { assert.NoError(t, orm.Close()) }() diff --git a/core/services/feeds/service_test.go b/core/services/feeds/service_test.go index 0dc07b57d43..536584a0846 100644 --- a/core/services/feeds/service_test.go +++ b/core/services/feeds/service_test.go @@ -178,7 +178,7 @@ func setupTestServiceCfg(t *testing.T, overrideCfg func(c *chainlink.Config, s * gcfg := configtest.NewGeneralConfig(t, overrideCfg) keyStore := new(ksmocks.Master) scopedConfig := evmtest.NewChainScopedConfig(t, gcfg) - ethKeyStore := cltest.NewKeyStore(t, db, gcfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: gcfg, HeadTracker: headtracker.NullTracker, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) diff --git a/core/services/fluxmonitorv2/flux_monitor_test.go b/core/services/fluxmonitorv2/flux_monitor_test.go index d8713fed997..2ac424bceab 100644 --- a/core/services/fluxmonitorv2/flux_monitor_test.go +++ b/core/services/fluxmonitorv2/flux_monitor_test.go @@ -275,7 +275,7 @@ func withORM(orm fluxmonitorv2.ORM) func(*setupOptions) { // setupStoreWithKey setups a new store and adds a key to the keystore func setupStoreWithKey(t *testing.T) (*sqlx.DB, common.Address) { db := pgtest.NewSqlxDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, pgtest.NewQConfig(true)).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, nodeAddr := cltest.MustInsertRandomKey(t, ethKeyStore) return db, nodeAddr @@ -283,8 +283,8 @@ func setupStoreWithKey(t *testing.T) (*sqlx.DB, common.Address) { // setupStoreWithKey setups a new store and adds a key to the keystore func setupFullDBWithKey(t *testing.T) (*sqlx.DB, common.Address) { - cfg, db := heavyweight.FullTestDBV2(t, nil) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + _, db := heavyweight.FullTestDBV2(t, nil) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, nodeAddr := cltest.MustInsertRandomKey(t, ethKeyStore) return db, nodeAddr diff --git a/core/services/fluxmonitorv2/key_store_test.go b/core/services/fluxmonitorv2/key_store_test.go index fdef2ade210..31e6c01e351 100644 --- a/core/services/fluxmonitorv2/key_store_test.go +++ b/core/services/fluxmonitorv2/key_store_test.go @@ -16,8 +16,7 @@ func TestKeyStore_EnabledKeysForChain(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) - ethKeyStore := cltest.NewKeyStore(t, db, cfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() ks := fluxmonitorv2.NewKeyStore(ethKeyStore) @@ -43,8 +42,7 @@ func TestKeyStore_GetRoundRobinAddress(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) - ethKeyStore := cltest.NewKeyStore(t, db, cfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, k0Address := cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/services/fluxmonitorv2/orm_test.go b/core/services/fluxmonitorv2/orm_test.go index f6904b9fe97..db00fabb4ff 100644 --- a/core/services/fluxmonitorv2/orm_test.go +++ b/core/services/fluxmonitorv2/orm_test.go @@ -89,7 +89,7 @@ func TestORM_UpdateFluxMonitorRoundStats(t *testing.T) { cfg := configtest.NewGeneralConfig(t, nil) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) lggr := logger.TestLogger(t) // Instantiate a real pipeline ORM because we need to create a pipeline run @@ -172,8 +172,7 @@ func TestORM_CreateEthTransaction(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := pgtest.NewQConfig(true) - ethKeyStore := cltest.NewKeyStore(t, db, cfg).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() strategy := commontxmmocks.NewTxStrategy(t) diff --git a/core/services/functions/listener_test.go b/core/services/functions/listener_test.go index d6cd9aa23d6..f3754bbbc29 100644 --- a/core/services/functions/listener_test.go +++ b/core/services/functions/listener_test.go @@ -85,7 +85,7 @@ func NewFunctionsListenerUniverse(t *testing.T, timeoutSec int, pruneFrequencySe mailMon := servicetest.Run(t, mailboxtest.NewMonitor(t)) db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + kst := cltest.NewKeyStore(t, db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, Client: ethClient, KeyStore: kst.Eth(), LogBroadcaster: broadcaster, MailMon: mailMon}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) diff --git a/core/services/job/helpers_test.go b/core/services/job/helpers_test.go index a7543753d63..b35389ad4ad 100644 --- a/core/services/job/helpers_test.go +++ b/core/services/job/helpers_test.go @@ -20,7 +20,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/evmtest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/chainlink" "github.com/smartcontractkit/chainlink/v2/core/services/job" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" @@ -214,7 +213,7 @@ func makeMinimalHTTPOracleSpec(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralC ExternalJobID: uuid.New(), } s := fmt.Sprintf(minimalNonBootstrapTemplate, contractAddress, transmitterAddress, keyBundle, fetchUrl, timeout) - keyStore := cltest.NewKeyStore(t, db, pgtest.NewQConfig(true)) + keyStore := cltest.NewKeyStore(t, db) relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: evmtest.NewEthClientMockWithDefaultChain(t), GeneralConfig: cfg, KeyStore: keyStore.Eth()}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) _, err := ocr.ValidatedOracleSpecToml(legacyChains, s) @@ -272,6 +271,7 @@ func makeOCRJobSpecFromToml(t *testing.T, jobSpecToml string) *job.Job { func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, cfg chainlink.GeneralConfig, transmitter common.Address, chainID *big.Int, fromBlock uint64) *job.Job { t.Helper() + ctx := testutils.Context(t) useForwarders := false _, beacon := cltest.MustInsertRandomKey(t, ks.Eth()) @@ -279,7 +279,7 @@ func makeOCR2VRFJobSpec(t testing.TB, ks keystore.Master, cfg chainlink.GeneralC _, feed := cltest.MustInsertRandomKey(t, ks.Eth()) _, dkg := cltest.MustInsertRandomKey(t, ks.Eth()) sendingKeys := fmt.Sprintf(`"%s"`, transmitter) - kb, _ := ks.OCR2().Create(chaintype.EVM) + kb, _ := ks.OCR2().Create(ctx, chaintype.EVM) vrfKey := make([]byte, 32) _, err := rand.Read(vrfKey) diff --git a/core/services/job/job_orm_test.go b/core/services/job/job_orm_test.go index c60f096c358..3cd94735ca8 100644 --- a/core/services/job/job_orm_test.go +++ b/core/services/job/job_orm_test.go @@ -74,13 +74,14 @@ serverPubKey = '8fa807463ad73f9ee855cfd60ba406dcf98a2855b3dd8af613107b0f6890a707 func TestORM(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -338,12 +339,13 @@ func TestORM(t *testing.T) { func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewGeneralConfig(t, nil) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -395,7 +397,7 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { }) t.Run("it creates and deletes records for vrf jobs", func(t *testing.T) { - key, err := keyStore.VRF().Create() + key, err := keyStore.VRF().Create(testutils.Context(t)) require.NoError(t, err) pk := key.PublicKey jb, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{PublicKey: pk.String()}).Toml()) @@ -438,10 +440,11 @@ func TestORM_DeleteJob_DeletesAssociatedRecords(t *testing.T) { } func TestORM_CreateJob_VRFV2(t *testing.T) { + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -522,10 +525,11 @@ func TestORM_CreateJob_VRFV2(t *testing.T) { } func TestORM_CreateJob_VRFV2Plus(t *testing.T) { + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -609,10 +613,11 @@ func TestORM_CreateJob_VRFV2Plus(t *testing.T) { } func TestORM_CreateJob_OCRBootstrap(t *testing.T) { + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -638,7 +643,7 @@ func TestORM_CreateJob_OCRBootstrap(t *testing.T) { func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { config := configtest.NewGeneralConfig(t, nil) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -720,6 +725,7 @@ func TestORM_CreateJob_EVMChainID_Validation(t *testing.T) { } func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { + ctx := testutils.Context(t) customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -732,8 +738,8 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { }) }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -789,6 +795,7 @@ func TestORM_CreateJob_OCR_DuplicatedContractAddress(t *testing.T) { } func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { + ctx := testutils.Context(t) customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -801,8 +808,8 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { }) }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -850,6 +857,7 @@ func TestORM_CreateJob_OCR2_DuplicatedContractAddress(t *testing.T) { } func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing.T) { + ctx := testutils.Context(t) customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -862,8 +870,8 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing }) }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) lggr := logger.TestLogger(t) pipelineORM := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) @@ -904,10 +912,11 @@ func TestORM_CreateJob_OCR2_Sending_Keys_Transmitter_Keys_Validations(t *testing } func TestORM_ValidateKeyStoreMatch(t *testing.T) { + ctx := testutils.Context(t) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) {}) - keyStore := cltest.NewKeyStore(t, pgtest.NewSqlxDB(t), config.Database()) - require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) + keyStore := cltest.NewKeyStore(t, pgtest.NewSqlxDB(t)) + require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) var jb job.Job { @@ -933,7 +942,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Cosmos key matching: \"bad key\"") - cosmosKey, err := keyStore.Cosmos().Create() + cosmosKey, err := keyStore.Cosmos().Create(ctx) require.NoError(t, err) err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, cosmosKey.ID()) require.NoError(t, err) @@ -946,7 +955,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Solana key matching: \"bad key\"") - solanaKey, err := keyStore.Solana().Create() + solanaKey, err := keyStore.Solana().Create(ctx) require.NoError(t, err) err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, solanaKey.ID()) require.NoError(t, err) @@ -958,7 +967,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no Starknet key matching: \"bad key\"") - starkNetKey, err := keyStore.StarkNet().Create() + starkNetKey, err := keyStore.StarkNet().Create(ctx) require.NoError(t, err) err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, starkNetKey.ID()) require.NoError(t, err) @@ -970,7 +979,7 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { err := job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, "bad key") require.EqualError(t, err, "no CSA key matching: \"bad key\"") - csaKey, err := keyStore.CSA().Create() + csaKey, err := keyStore.CSA().Create(ctx) require.NoError(t, err) err = job.ValidateKeyStoreMatch(ctx, jb.OCR2OracleSpec, keyStore, csaKey.ID()) require.NoError(t, err) @@ -979,12 +988,13 @@ func TestORM_ValidateKeyStoreMatch(t *testing.T) { func Test_FindJobs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1047,6 +1057,7 @@ func Test_FindJobs(t *testing.T) { func Test_FindJob(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) // Create a config with multiple EVM chains. The test fixtures already load 1337 // Additional chains will need additional fixture statements to add a chain to evm_chains. @@ -1062,10 +1073,10 @@ func Test_FindJob(t *testing.T) { }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) - require.NoError(t, keyStore.CSA().Add(cltest.DefaultCSAKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + require.NoError(t, keyStore.CSA().Add(ctx, cltest.DefaultCSAKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1244,11 +1255,12 @@ func Test_FindJob(t *testing.T) { func Test_FindJobsByPipelineSpecIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1291,12 +1303,13 @@ func Test_FindJobsByPipelineSpecIDs(t *testing.T) { func Test_FindPipelineRuns(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1351,13 +1364,14 @@ func Test_FindPipelineRuns(t *testing.T) { func Test_PipelineRunsByJobID(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1410,14 +1424,15 @@ func Test_PipelineRunsByJobID(t *testing.T) { } func Test_FindPipelineRunIDsByJobID(t *testing.T) { + ctx := testutils.Context(t) var jb job.Job config := configtest.NewTestGeneralConfig(t) _, db := heavyweight.FullTestDBV2(t, nil) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1519,13 +1534,14 @@ func Test_FindPipelineRunIDsByJobID(t *testing.T) { func Test_FindPipelineRunsByIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) @@ -1577,12 +1593,13 @@ func Test_FindPipelineRunsByIDs(t *testing.T) { func Test_FindPipelineRunByID(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - err := keyStore.OCR().Add(cltest.DefaultOCRKey) + keyStore := cltest.NewKeyStore(t, db) + err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey) require.NoError(t, err) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) @@ -1620,12 +1637,13 @@ func Test_FindPipelineRunByID(t *testing.T) { func Test_FindJobWithoutSpecErrors(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - err := keyStore.OCR().Add(cltest.DefaultOCRKey) + keyStore := cltest.NewKeyStore(t, db) + err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey) require.NoError(t, err) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) @@ -1657,12 +1675,13 @@ func Test_FindJobWithoutSpecErrors(t *testing.T) { func Test_FindSpecErrorsByJobIDs(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - err := keyStore.OCR().Add(cltest.DefaultOCRKey) + keyStore := cltest.NewKeyStore(t, db) + err := keyStore.OCR().Add(ctx, cltest.DefaultOCRKey) require.NoError(t, err) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) @@ -1691,13 +1710,14 @@ func Test_FindSpecErrorsByJobIDs(t *testing.T) { func Test_CountPipelineRunsByJobID(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) diff --git a/core/services/job/job_pipeline_orm_integration_test.go b/core/services/job/job_pipeline_orm_integration_test.go index 696005c270e..33ee6dc306c 100644 --- a/core/services/job/job_pipeline_orm_integration_test.go +++ b/core/services/job/job_pipeline_orm_integration_test.go @@ -29,6 +29,7 @@ func clearJobsDb(t *testing.T, db *sqlx.DB) { } func TestPipelineORM_Integration(t *testing.T) { + ctx := testutils.Context(t) const DotStr = ` // data source 1 ds1 [type=bridge name=voter_turnout]; @@ -51,11 +52,11 @@ func TestPipelineORM_Integration(t *testing.T) { c.JobPipeline.HTTPRequest.DefaultTimeout = commonconfig.MustNewDuration(30 * time.Millisecond) }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() _, transmitterAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) var specID int32 diff --git a/core/services/job/kv_orm_test.go b/core/services/job/kv_orm_test.go index 3ba03b8bc3c..156779ffb4d 100644 --- a/core/services/job/kv_orm_test.go +++ b/core/services/job/kv_orm_test.go @@ -34,7 +34,7 @@ func TestJobKVStore(t *testing.T) { jobID := int32(1337) kvStore := job.NewKVStore(jobID, db, config.Database(), lggr) - jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db, config.Database()), config.Database()) + jobORM := NewTestORM(t, db, pipelineORM, bridgesORM, cltest.NewKeyStore(t, db), config.Database()) jb, err := directrequest.ValidatedDirectRequestSpec(testspecs.GetDirectRequestSpec()) require.NoError(t, err) diff --git a/core/services/job/runner_integration_test.go b/core/services/job/runner_integration_test.go index 6149bb71cf6..e13b1025b8b 100644 --- a/core/services/job/runner_integration_test.go +++ b/core/services/job/runner_integration_test.go @@ -54,17 +54,18 @@ import ( var monitoringEndpoint = telemetry.MonitoringEndpointGenerator(&telemetry.NoopAgent{}) func TestRunner(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, pgtest.NewQConfig(true)) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() _, transmitterAddress := cltest.MustInsertRandomKey(t, ethKeyStore) - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} - kb, err := keyStore.OCR().Create() + kb, err := keyStore.OCR().Create(ctx) require.NoError(t, err) kbid := models.MustSha256HashFromHex(kb.ID()) c.OCR.KeyBundleID = &kbid @@ -79,7 +80,6 @@ func TestRunner(t *testing.T) { ethClient.On("HeadByNumber", mock.Anything, (*big.Int)(nil)).Return(cltest.Head(10), nil) ethClient.On("CallContract", mock.Anything, mock.Anything, mock.Anything).Maybe().Return(nil, nil) - ctx := testutils.Context(t) pipelineORM := pipeline.NewORM(db, logger.TestLogger(t), config.JobPipeline().MaxSuccessfulRuns()) require.NoError(t, pipelineORM.Start(ctx)) t.Cleanup(func() { assert.NoError(t, pipelineORM.Close()) }) @@ -437,6 +437,7 @@ answer1 [type=median index=0]; }) t.Run("minimal bootstrap", func(t *testing.T) { + ctx := testutils.Context(t) s := ` type = "offchainreporting" schemaVersion = 1 @@ -454,7 +455,7 @@ answer1 [type=median index=0]; require.NoError(t, err) lggr := logger.TestLogger(t) - _, err = keyStore.P2P().Create() + _, err = keyStore.P2P().Create(ctx) assert.NoError(t, err) pw := ocrcommon.NewSingletonPeerWrapper(keyStore, config.P2P(), config.OCR(), config.Database(), db, lggr) servicetest.Run(t, pw) @@ -475,7 +476,8 @@ answer1 [type=median index=0]; }) t.Run("test min non-bootstrap", func(t *testing.T) { - kb, err := keyStore.OCR().Create() + ctx := testutils.Context(t) + kb, err := keyStore.OCR().Create(ctx) require.NoError(t, err) s := fmt.Sprintf(minimalNonBootstrapTemplate, cltest.NewEIP55Address(), transmitterAddress.Hex(), kb.ID(), "http://blah.com", "") @@ -537,6 +539,7 @@ answer1 [type=median index=0]; }) t.Run("test enhanced telemetry service creation", func(t *testing.T) { + ctx := testutils.Context(t) testCases := []struct { jbCaptureEATelemetry bool specCaptureEATelemetry bool @@ -558,7 +561,7 @@ answer1 [type=median index=0]; relayExtenders = evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, Client: ethClient, GeneralConfig: config, KeyStore: ethKeyStore}) legacyChains = evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) - kb, err := keyStore.OCR().Create() + kb, err := keyStore.OCR().Create(ctx) require.NoError(t, err) s := fmt.Sprintf(minimalNonBootstrapTemplate, cltest.NewEIP55Address(), transmitterAddress.Hex(), kb.ID(), "http://blah.com", "") @@ -606,8 +609,9 @@ answer1 [type=median index=0]; }) t.Run("test job spec error is created", func(t *testing.T) { + ctx := testutils.Context(t) // Create a keystore with an ocr key bundle and p2p key. - kb, err := keyStore.OCR().Create() + kb, err := keyStore.OCR().Create(ctx) require.NoError(t, err) spec := fmt.Sprintf(ocrJobSpecTemplate, testutils.NewAddress().Hex(), kb.ID(), transmitterAddress.Hex(), fmt.Sprintf(simpleFetchDataSourceTemplate, "blah", true)) jb := makeOCRJobSpecFromToml(t, spec) @@ -636,7 +640,6 @@ answer1 [type=median index=0]; // Return an error getting the contract code. ethClient.On("CodeAt", mock.Anything, mock.Anything, mock.Anything).Return(nil, errors.New("no such code")) - ctx := testutils.Context(t) for _, s := range services { err = s.Start(ctx) require.NoError(t, err) diff --git a/core/services/job/spawner_test.go b/core/services/job/spawner_test.go index 802763cfaab..d3927da6590 100644 --- a/core/services/job/spawner_test.go +++ b/core/services/job/spawner_test.go @@ -75,14 +75,15 @@ func (g *relayGetter) Get(id relay.ID) (loop.Relayer, error) { func TestSpawner_CreateJobDeleteJob(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) config := configtest.NewTestGeneralConfig(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() - require.NoError(t, keyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, keyStore.P2P().Add(cltest.DefaultP2PKey)) - require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) + require.NoError(t, keyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, keyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) + require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) _, address := cltest.MustInsertRandomKey(t, ethKeyStore) _, bridge := cltest.MustCreateBridge(t, db, cltest.BridgeOpts{}) diff --git a/core/services/keeper/orm_test.go b/core/services/keeper/orm_test.go index 1e5d927fe2f..3d305f3e2b1 100644 --- a/core/services/keeper/orm_test.go +++ b/core/services/keeper/orm_test.go @@ -76,8 +76,8 @@ func assertLastRunHeight(t *testing.T, db *sqlx.DB, upkeep keeper.UpkeepRegistra func TestKeeperDB_Registries(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) @@ -90,8 +90,8 @@ func TestKeeperDB_Registries(t *testing.T) { func TestKeeperDB_RegistryByContractAddress(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) @@ -104,8 +104,8 @@ func TestKeeperDB_RegistryByContractAddress(t *testing.T) { func TestKeeperDB_UpsertUpkeep(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) upkeep := keeper.UpkeepRegistration{ @@ -140,8 +140,8 @@ func TestKeeperDB_UpsertUpkeep(t *testing.T) { func TestKeeperDB_BatchDeleteUpkeepsForJob(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, job := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) @@ -167,8 +167,8 @@ func TestKeeperDB_BatchDeleteUpkeepsForJob(t *testing.T) { func TestKeeperDB_EligibleUpkeeps_Shuffle(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() blockheight := int64(63) gracePeriod := int64(10) @@ -198,8 +198,8 @@ func TestKeeperDB_EligibleUpkeeps_Shuffle(t *testing.T) { func TestKeeperDB_NewEligibleUpkeeps_GracePeriod(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) @@ -226,8 +226,8 @@ func TestKeeperDB_NewEligibleUpkeeps_GracePeriod(t *testing.T) { func TestKeeperDB_EligibleUpkeeps_TurnsRandom(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 3, 10) @@ -270,8 +270,8 @@ func TestKeeperDB_EligibleUpkeeps_TurnsRandom(t *testing.T) { func TestKeeperDB_NewEligibleUpkeeps_SkipIfLastPerformedByCurrentKeeper(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) @@ -293,8 +293,8 @@ func TestKeeperDB_NewEligibleUpkeeps_SkipIfLastPerformedByCurrentKeeper(t *testi func TestKeeperDB_NewEligibleUpkeeps_CoverBuddy(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 1, 2, 20) @@ -318,8 +318,8 @@ func TestKeeperDB_NewEligibleUpkeeps_CoverBuddy(t *testing.T) { func TestKeeperDB_NewEligibleUpkeeps_FirstTurn(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 2, 20) @@ -340,8 +340,8 @@ func TestKeeperDB_NewEligibleUpkeeps_FirstTurn(t *testing.T) { func TestKeeperDB_NewEligibleUpkeeps_FiltersByRegistry(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry1, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) registry2, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) @@ -365,8 +365,8 @@ func TestKeeperDB_NewEligibleUpkeeps_FiltersByRegistry(t *testing.T) { func TestKeeperDB_AllUpkeepIDsForRegistry(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, _ := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) upkeepIDs, err := orm.AllUpkeepIDsForRegistry(ctx, registry.ID) @@ -394,8 +394,8 @@ func TestKeeperDB_AllUpkeepIDsForRegistry(t *testing.T) { func TestKeeperDB_UpdateUpkeepLastKeeperIndex(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, j := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) @@ -409,8 +409,8 @@ func TestKeeperDB_UpdateUpkeepLastKeeperIndex(t *testing.T) { func TestKeeperDB_NewSetLastRunInfoForUpkeepOnJob(t *testing.T) { t.Parallel() ctx := testutils.Context(t) - db, config, orm := setupKeeperDB(t) - ethKeyStore := cltest.NewKeyStore(t, db, config.Database()).Eth() + db, _, orm := setupKeeperDB(t) + ethKeyStore := cltest.NewKeyStore(t, db).Eth() registry, j := cltest.MustInsertKeeperRegistry(t, db, orm, ethKeyStore, 0, 1, 20) upkeep := cltest.MustInsertUpkeepForRegistry(t, db, registry) diff --git a/core/services/keeper/registry_synchronizer_helper_test.go b/core/services/keeper/registry_synchronizer_helper_test.go index c97d3c0c92c..2726c9a754d 100644 --- a/core/services/keeper/registry_synchronizer_helper_test.go +++ b/core/services/keeper/registry_synchronizer_helper_test.go @@ -40,7 +40,7 @@ func setupRegistrySync(t *testing.T, version keeper.RegistryVersion) ( cfg := configtest.NewGeneralConfig(t, nil) korm := keeper.NewORM(db, logger.TestLogger(t)) ethClient := evmtest.NewEthClientMockWithDefaultChain(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) lbMock := logmocks.NewBroadcaster(t) lbMock.On("AddDependents", 1).Maybe() j := cltest.MustInsertKeeperJob(t, db, korm, cltest.NewEIP55Address(), cltest.NewEIP55Address()) diff --git a/core/services/keeper/upkeep_executer_test.go b/core/services/keeper/upkeep_executer_test.go index 10995ec3c0d..33850ea7134 100644 --- a/core/services/keeper/upkeep_executer_test.go +++ b/core/services/keeper/upkeep_executer_test.go @@ -75,7 +75,7 @@ func setup(t *testing.T, estimator gas.EvmFeeEstimator, overrideFn func(c *chain } }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ethClient := evmtest.NewEthClientMock(t) ethClient.On("ConfiguredChainID").Return(cfg.EVMConfigs()[0].ChainID.ToInt()).Maybe() ethClient.On("IsL2").Return(false).Maybe() diff --git a/core/services/keystore/cosmos.go b/core/services/keystore/cosmos.go index e3549fdb932..76fc5f39816 100644 --- a/core/services/keystore/cosmos.go +++ b/core/services/keystore/cosmos.go @@ -15,12 +15,12 @@ import ( type Cosmos interface { Get(id string) (cosmoskey.Key, error) GetAll() ([]cosmoskey.Key, error) - Create() (cosmoskey.Key, error) - Add(key cosmoskey.Key) error - Delete(id string) (cosmoskey.Key, error) - Import(keyJSON []byte, password string) (cosmoskey.Key, error) + Create(ctx context.Context) (cosmoskey.Key, error) + Add(ctx context.Context, key cosmoskey.Key) error + Delete(ctx context.Context, id string) (cosmoskey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (cosmoskey.Key, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } type cosmos struct { @@ -56,17 +56,17 @@ func (ks *cosmos) GetAll() (keys []cosmoskey.Key, _ error) { return keys, nil } -func (ks *cosmos) Create() (cosmoskey.Key, error) { +func (ks *cosmos) Create(ctx context.Context) (cosmoskey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { return cosmoskey.Key{}, ErrLocked } key := cosmoskey.New() - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *cosmos) Add(key cosmoskey.Key) error { +func (ks *cosmos) Add(ctx context.Context, key cosmoskey.Key) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -75,10 +75,10 @@ func (ks *cosmos) Add(key cosmoskey.Key) error { if _, found := ks.keyRing.Cosmos[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *cosmos) Delete(id string) (cosmoskey.Key, error) { +func (ks *cosmos) Delete(ctx context.Context, id string) (cosmoskey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -88,11 +88,11 @@ func (ks *cosmos) Delete(id string) (cosmoskey.Key, error) { if err != nil { return cosmoskey.Key{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *cosmos) Import(keyJSON []byte, password string) (cosmoskey.Key, error) { +func (ks *cosmos) Import(ctx context.Context, keyJSON []byte, password string) (cosmoskey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -105,7 +105,7 @@ func (ks *cosmos) Import(keyJSON []byte, password string) (cosmoskey.Key, error) if _, found := ks.keyRing.Cosmos[key.ID()]; found { return cosmoskey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *cosmos) Export(id string, password string) ([]byte, error) { @@ -121,7 +121,7 @@ func (ks *cosmos) Export(id string, password string) ([]byte, error) { return key.ToEncryptedJSON(password, ks.scryptParams) } -func (ks *cosmos) EnsureKey() error { +func (ks *cosmos) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -136,7 +136,7 @@ func (ks *cosmos) EnsureKey() error { ks.logger.Infof("Created Cosmos key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } func (ks *cosmos) getByID(id string) (cosmoskey.Key, error) { diff --git a/core/services/keystore/cosmos_test.go b/core/services/keystore/cosmos_test.go index 30c669f7545..cad6dd67654 100644 --- a/core/services/keystore/cosmos_test.go +++ b/core/services/keystore/cosmos_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -8,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" @@ -16,15 +17,15 @@ import ( func Test_CosmosKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.Cosmos() reset := func() { + ctx := context.Background() // Executed during cleanup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -42,7 +43,8 @@ func Test_CosmosKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -51,21 +53,22 @@ func Test_CosmosKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) _, err = ks.Export("non-existent", cltest.Password) assert.Error(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) - _, err = ks.Import(exportJSON, cltest.Password) + _, err = ks.Import(ctx, exportJSON, cltest.Password) assert.Error(t, err) - _, err = ks.Import([]byte(""), cltest.Password) + _, err = ks.Import(ctx, []byte(""), cltest.Password) assert.Error(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -75,17 +78,18 @@ func Test_CosmosKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey := cosmoskey.New() - err := ks.Add(newKey) + err := ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) assert.Error(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -96,10 +100,11 @@ func Test_CosmosKeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKey() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) assert.NoError(t, err) - err = ks.EnsureKey() + err = ks.EnsureKey(ctx) assert.NoError(t, err) keys, err := ks.GetAll() diff --git a/core/services/keystore/csa.go b/core/services/keystore/csa.go index 01491b85b35..21b530c0650 100644 --- a/core/services/keystore/csa.go +++ b/core/services/keystore/csa.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "github.com/pkg/errors" @@ -17,12 +18,12 @@ var ErrCSAKeyExists = errors.New("can only have 1 CSA key") type CSA interface { Get(id string) (csakey.KeyV2, error) GetAll() ([]csakey.KeyV2, error) - Create() (csakey.KeyV2, error) - Add(key csakey.KeyV2) error - Delete(id string) (csakey.KeyV2, error) - Import(keyJSON []byte, password string) (csakey.KeyV2, error) + Create(ctx context.Context) (csakey.KeyV2, error) + Add(ctx context.Context, key csakey.KeyV2) error + Delete(ctx context.Context, id string) (csakey.KeyV2, error) + Import(ctx context.Context, keyJSON []byte, password string) (csakey.KeyV2, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } type csa struct { @@ -58,7 +59,7 @@ func (ks *csa) GetAll() (keys []csakey.KeyV2, _ error) { return keys, nil } -func (ks *csa) Create() (csakey.KeyV2, error) { +func (ks *csa) Create(ctx context.Context) (csakey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -74,10 +75,10 @@ func (ks *csa) Create() (csakey.KeyV2, error) { if err != nil { return csakey.KeyV2{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *csa) Add(key csakey.KeyV2) error { +func (ks *csa) Add(ctx context.Context, key csakey.KeyV2) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -86,10 +87,10 @@ func (ks *csa) Add(key csakey.KeyV2) error { if len(ks.keyRing.CSA) > 0 { return ErrCSAKeyExists } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *csa) Delete(id string) (csakey.KeyV2, error) { +func (ks *csa) Delete(ctx context.Context, id string) (csakey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -100,12 +101,12 @@ func (ks *csa) Delete(id string) (csakey.KeyV2, error) { return csakey.KeyV2{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *csa) Import(keyJSON []byte, password string) (csakey.KeyV2, error) { +func (ks *csa) Import(ctx context.Context, keyJSON []byte, password string) (csakey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -118,7 +119,7 @@ func (ks *csa) Import(keyJSON []byte, password string) (csakey.KeyV2, error) { if _, found := ks.keyRing.CSA[key.ID()]; found { return csakey.KeyV2{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *csa) Export(id string, password string) ([]byte, error) { @@ -135,7 +136,7 @@ func (ks *csa) Export(id string, password string) ([]byte, error) { } // EnsureKey verifies whether the CSA key has been seeded, if not, it creates it. -func (ks *csa) EnsureKey() error { +func (ks *csa) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -153,7 +154,7 @@ func (ks *csa) EnsureKey() error { ks.logger.Infof("Created CSA key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } func (ks *csa) getByID(id string) (csakey.KeyV2, error) { diff --git a/core/services/keystore/csa_test.go b/core/services/keystore/csa_test.go index b6dfb009593..84d79798011 100644 --- a/core/services/keystore/csa_test.go +++ b/core/services/keystore/csa_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "fmt" "testing" @@ -9,7 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" @@ -17,15 +18,15 @@ import ( func Test_CSAKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.CSA() reset := func() { + ctx := context.Background() // Executed on cleanup _, err := db.Exec("DELETE FROM encrypted_key_rings") require.NoError(t, err) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -43,14 +44,16 @@ func Test_CSAKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) require.Equal(t, key, retrievedKey) t.Run("prevents creating more than one key", func(t *testing.T) { - k, err2 := ks.Create() + ctx := testutils.Context(t) + k, err2 := ks.Create(ctx) assert.Zero(t, k) assert.Error(t, err2) @@ -60,15 +63,16 @@ func Test_CSAKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -76,7 +80,7 @@ func Test_CSAKeyStore_E2E(t *testing.T) { require.Equal(t, importedKey, retrievedKey) t.Run("prevents importing more than one key", func(t *testing.T) { - k, err2 := ks.Import(exportJSON, cltest.Password) + k, err2 := ks.Import(testutils.Context(t), exportJSON, cltest.Password) assert.Zero(t, k) assert.Error(t, err2) @@ -84,7 +88,7 @@ func Test_CSAKeyStore_E2E(t *testing.T) { }) t.Run("fails to import malformed key", func(t *testing.T) { - k, err2 := ks.Import([]byte(""), cltest.Password) + k, err2 := ks.Import(testutils.Context(t), []byte(""), cltest.Password) assert.Zero(t, k) assert.Error(t, err2) @@ -100,14 +104,15 @@ func Test_CSAKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := csakey.NewV2() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -116,17 +121,18 @@ func Test_CSAKeyStore_E2E(t *testing.T) { require.Error(t, err) t.Run("prevents adding more than one key", func(t *testing.T) { - err = ks.Add(newKey) + ctx := testutils.Context(t) + err = ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) assert.True(t, errors.Is(err, keystore.ErrCSAKeyExists)) }) t.Run("fails to delete non-existent key", func(t *testing.T) { - k, err2 := ks.Delete("non-existent") + k, err2 := ks.Delete(testutils.Context(t), "non-existent") assert.Zero(t, k) assert.Error(t, err2) @@ -135,13 +141,14 @@ func Test_CSAKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key/ensures it already exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := csakey.NewV2() assert.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.NoError(t, err) - err = keyStore.CSA().EnsureKey() + err = keyStore.CSA().EnsureKey(ctx) assert.NoError(t, err) keys, err2 := ks.GetAll() assert.NoError(t, err2) @@ -154,12 +161,13 @@ func Test_CSAKeyStore_E2E(t *testing.T) { t.Run("auto creates a key if it doesn't exists when trying to ensure it already exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) keys, err := ks.GetAll() assert.NoError(t, err) assert.Equal(t, 0, len(keys)) - err = keyStore.CSA().EnsureKey() + err = keyStore.CSA().EnsureKey(ctx) assert.NoError(t, err) keys, err = ks.GetAll() diff --git a/core/services/keystore/dkgencrypt.go b/core/services/keystore/dkgencrypt.go index c5d02034dad..15d0ae8b24d 100644 --- a/core/services/keystore/dkgencrypt.go +++ b/core/services/keystore/dkgencrypt.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "github.com/pkg/errors" @@ -14,12 +15,12 @@ import ( type DKGEncrypt interface { Get(id string) (dkgencryptkey.Key, error) GetAll() ([]dkgencryptkey.Key, error) - Create() (dkgencryptkey.Key, error) - Add(key dkgencryptkey.Key) error - Delete(id string) (dkgencryptkey.Key, error) - Import(keyJSON []byte, password string) (dkgencryptkey.Key, error) + Create(ctx context.Context) (dkgencryptkey.Key, error) + Add(ctx context.Context, key dkgencryptkey.Key) error + Delete(ctx context.Context, id string) (dkgencryptkey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (dkgencryptkey.Key, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } type dkgEncrypt struct { @@ -35,17 +36,17 @@ func newDKGEncryptKeyStore(km *keyManager) *dkgEncrypt { var _ DKGEncrypt = &dkgEncrypt{} // Add implements DKGEncrypt -func (d *dkgEncrypt) Add(key dkgencryptkey.Key) error { +func (d *dkgEncrypt) Add(ctx context.Context, key dkgencryptkey.Key) error { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { return ErrLocked } - return d.safeAddKey(key) + return d.safeAddKey(ctx, key) } // Create implements DKGEncrypt -func (d *dkgEncrypt) Create() (dkgencryptkey.Key, error) { +func (d *dkgEncrypt) Create(ctx context.Context) (dkgencryptkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -55,11 +56,11 @@ func (d *dkgEncrypt) Create() (dkgencryptkey.Key, error) { if err != nil { return dkgencryptkey.Key{}, errors.Wrap(err, "dkgencryptkey.New()") } - return key, d.safeAddKey(key) + return key, d.safeAddKey(ctx, key) } // Delete implements DKGEncrypt -func (d *dkgEncrypt) Delete(id string) (dkgencryptkey.Key, error) { +func (d *dkgEncrypt) Delete(ctx context.Context, id string) (dkgencryptkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -70,12 +71,12 @@ func (d *dkgEncrypt) Delete(id string) (dkgencryptkey.Key, error) { return dkgencryptkey.Key{}, err } - err = d.safeRemoveKey(key) + err = d.safeRemoveKey(ctx, key) return key, errors.Wrap(err, "safe remove key") } // EnsureKey implements DKGEncrypt -func (d *dkgEncrypt) EnsureKey() error { +func (d *dkgEncrypt) EnsureKey(ctx context.Context) error { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -92,7 +93,7 @@ func (d *dkgEncrypt) EnsureKey() error { d.logger.Infof("Created DKGEncrypt key with ID %s", key.ID()) - return d.safeAddKey(key) + return d.safeAddKey(ctx, key) } // Export implements DKGEncrypt @@ -133,7 +134,7 @@ func (d *dkgEncrypt) GetAll() (keys []dkgencryptkey.Key, err error) { } // Import implements DKGEncrypt -func (d *dkgEncrypt) Import(keyJSON []byte, password string) (dkgencryptkey.Key, error) { +func (d *dkgEncrypt) Import(ctx context.Context, keyJSON []byte, password string) (dkgencryptkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -147,7 +148,7 @@ func (d *dkgEncrypt) Import(keyJSON []byte, password string) (dkgencryptkey.Key, if err == nil { return dkgencryptkey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, d.keyManager.safeAddKey(key) + return key, d.keyManager.safeAddKey(ctx, key) } // caller must hold lock diff --git a/core/services/keystore/dkgencrypt_test.go b/core/services/keystore/dkgencrypt_test.go index 36f48f9c2b4..4856473a0df 100644 --- a/core/services/keystore/dkgencrypt_test.go +++ b/core/services/keystore/dkgencrypt_test.go @@ -1,13 +1,14 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" @@ -15,18 +16,18 @@ import ( func Test_DKGEncryptKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.DKGEncrypt() assert.NotNil(t, ks) reset := func() { + ctx := context.Background() // Executed on cleanup _, err := db.Exec("DELETE FROM encrypted_key_rings") require.NoError(t, err) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -44,7 +45,8 @@ func Test_DKGEncryptKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -53,15 +55,16 @@ func Test_DKGEncryptKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -71,14 +74,15 @@ func Test_DKGEncryptKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := dkgencryptkey.New() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -89,13 +93,14 @@ func Test_DKGEncryptKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key/ensures it already exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := dkgencryptkey.New() assert.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.NoError(t, err) - err = keyStore.DKGEncrypt().EnsureKey() + err = keyStore.DKGEncrypt().EnsureKey(ctx) assert.NoError(t, err) keys, err2 := ks.GetAll() assert.NoError(t, err2) @@ -107,12 +112,13 @@ func Test_DKGEncryptKeyStore_E2E(t *testing.T) { t.Run("auto creates a key if it doesn't exists when trying to ensure it already exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) keys, err := ks.GetAll() assert.NoError(t, err) assert.Equal(t, 0, len(keys)) - err = keyStore.DKGEncrypt().EnsureKey() + err = keyStore.DKGEncrypt().EnsureKey(ctx) assert.NoError(t, err) keys, err = ks.GetAll() diff --git a/core/services/keystore/dkgsign.go b/core/services/keystore/dkgsign.go index e609b441831..385323fc0fa 100644 --- a/core/services/keystore/dkgsign.go +++ b/core/services/keystore/dkgsign.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "github.com/pkg/errors" @@ -14,12 +15,12 @@ import ( type DKGSign interface { Get(id string) (dkgsignkey.Key, error) GetAll() ([]dkgsignkey.Key, error) - Create() (dkgsignkey.Key, error) - Add(key dkgsignkey.Key) error - Delete(id string) (dkgsignkey.Key, error) - Import(keyJSON []byte, password string) (dkgsignkey.Key, error) + Create(ctx context.Context) (dkgsignkey.Key, error) + Add(ctx context.Context, key dkgsignkey.Key) error + Delete(ctx context.Context, id string) (dkgsignkey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (dkgsignkey.Key, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } type dkgSign struct { @@ -35,17 +36,17 @@ func newDKGSignKeyStore(km *keyManager) *dkgSign { var _ DKGSign = &dkgSign{} // Add implements DKGSign -func (d *dkgSign) Add(key dkgsignkey.Key) error { +func (d *dkgSign) Add(ctx context.Context, key dkgsignkey.Key) error { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { return ErrLocked } - return d.safeAddKey(key) + return d.safeAddKey(ctx, key) } // Create implements DKGSign -func (d *dkgSign) Create() (dkgsignkey.Key, error) { +func (d *dkgSign) Create(ctx context.Context) (dkgsignkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -55,11 +56,11 @@ func (d *dkgSign) Create() (dkgsignkey.Key, error) { if err != nil { return dkgsignkey.Key{}, errors.Wrap(err, "dkgsignkey New()") } - return key, d.safeAddKey(key) + return key, d.safeAddKey(ctx, key) } // Delete implements DKGSign -func (d *dkgSign) Delete(id string) (dkgsignkey.Key, error) { +func (d *dkgSign) Delete(ctx context.Context, id string) (dkgsignkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -70,12 +71,12 @@ func (d *dkgSign) Delete(id string) (dkgsignkey.Key, error) { return dkgsignkey.Key{}, err } - err = d.safeRemoveKey(key) + err = d.safeRemoveKey(ctx, key) return key, errors.Wrap(err, "safe remove key") } // EnsureKey implements DKGSign -func (d *dkgSign) EnsureKey() error { +func (d *dkgSign) EnsureKey(ctx context.Context) error { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -92,7 +93,7 @@ func (d *dkgSign) EnsureKey() error { d.logger.Infof("Created DKGSign key with ID %s", key.ID()) - return d.safeAddKey(key) + return d.safeAddKey(ctx, key) } // Export implements DKGSign @@ -133,7 +134,7 @@ func (d *dkgSign) GetAll() (keys []dkgsignkey.Key, err error) { } // Import implements DKGSign -func (d *dkgSign) Import(keyJSON []byte, password string) (dkgsignkey.Key, error) { +func (d *dkgSign) Import(ctx context.Context, keyJSON []byte, password string) (dkgsignkey.Key, error) { d.lock.Lock() defer d.lock.Unlock() if d.isLocked() { @@ -147,7 +148,7 @@ func (d *dkgSign) Import(keyJSON []byte, password string) (dkgsignkey.Key, error if err == nil { return dkgsignkey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, d.keyManager.safeAddKey(key) + return key, d.keyManager.safeAddKey(ctx, key) } // caller must hold lock diff --git a/core/services/keystore/dkgsign_test.go b/core/services/keystore/dkgsign_test.go index 5ea23a516be..8aa8cb1ad74 100644 --- a/core/services/keystore/dkgsign_test.go +++ b/core/services/keystore/dkgsign_test.go @@ -1,13 +1,14 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" @@ -15,18 +16,18 @@ import ( func Test_DKGSignKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.DKGSign() assert.NotNil(t, ks) reset := func() { + ctx := context.Background() // Executed on cleanup _, err := db.Exec("DELETE FROM encrypted_key_rings") require.NoError(t, err) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -44,7 +45,8 @@ func Test_DKGSignKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -53,15 +55,16 @@ func Test_DKGSignKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -71,14 +74,15 @@ func Test_DKGSignKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := dkgsignkey.New() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -89,13 +93,13 @@ func Test_DKGSignKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key/ensures it already exists", func(t *testing.T) { defer reset() - + ctx := testutils.Context(t) newKey, err := dkgsignkey.New() assert.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.NoError(t, err) - err = keyStore.DKGSign().EnsureKey() + err = keyStore.DKGSign().EnsureKey(ctx) assert.NoError(t, err) keys, err2 := ks.GetAll() assert.NoError(t, err2) @@ -107,12 +111,13 @@ func Test_DKGSignKeyStore_E2E(t *testing.T) { t.Run("auto creates a key if it doesn't exists when trying to ensure it already exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) keys, err := ks.GetAll() assert.NoError(t, err) assert.Equal(t, 0, len(keys)) - err = keyStore.DKGSign().EnsureKey() + err = keyStore.DKGSign().EnsureKey(ctx) assert.NoError(t, err) keys, err = ks.GetAll() diff --git a/core/services/keystore/eth.go b/core/services/keystore/eth.go index be59cb5e54c..a4365eb9092 100644 --- a/core/services/keystore/eth.go +++ b/core/services/keystore/eth.go @@ -13,8 +13,8 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -29,9 +29,9 @@ type Eth interface { Import(ctx context.Context, keyJSON []byte, password string, chainIDs ...*big.Int) (ethkey.KeyV2, error) Export(ctx context.Context, id string, password string) ([]byte, error) - Enable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error - Disable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error - Add(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error + Enable(ctx context.Context, address common.Address, chainID *big.Int) error + Disable(ctx context.Context, address common.Address, chainID *big.Int) error + Add(ctx context.Context, address common.Address, chainID *big.Int) error EnsureKeys(ctx context.Context, chainIDs ...*big.Int) error SubscribeToKeyChanges(ctx context.Context) (ch chan struct{}, unsub func()) @@ -55,18 +55,18 @@ type Eth interface { type eth struct { *keyManager keystateORM - q pg.Q + ds sqlutil.DataSource subscribers [](chan struct{}) subscribersMu *sync.RWMutex } var _ Eth = ð{} -func newEthKeyStore(km *keyManager, orm keystateORM, q pg.Q) *eth { +func newEthKeyStore(km *keyManager, orm keystateORM, ds sqlutil.DataSource) *eth { return ð{ keystateORM: orm, keyManager: km, - q: q, + ds: ds, subscribers: make([](chan struct{}), 0), subscribersMu: new(sync.RWMutex), } @@ -111,9 +111,10 @@ func (ks *eth) Create(ctx context.Context, chainIDs ...*big.Int) (ethkey.KeyV2, return ethkey.KeyV2{}, err } err = ks.add(ctx, key, chainIDs...) - if err == nil { - ks.notify() + if err != nil { + return ethkey.KeyV2{}, errors.Wrap(err, "unable to add eth key") } + ks.notify() ks.logger.Infow(fmt.Sprintf("Created EVM key with ID %s", key.Address.Hex()), "address", key.Address.Hex(), "evmChainIDs", chainIDs) return key, err } @@ -139,7 +140,7 @@ func (ks *eth) EnsureKeys(ctx context.Context, chainIDs ...*big.Int) (err error) } err = ks.add(ctx, newKey, chainID) if err != nil { - return err + return fmt.Errorf("failed to add key %s for chain %s: %w", newKey.Address, chainID, err) } ks.logger.Infow(fmt.Sprintf("Created EVM key with ID %s", newKey.Address.Hex()), "address", newKey.Address.Hex(), "evmChainID", chainID) } @@ -182,27 +183,29 @@ func (ks *eth) Export(ctx context.Context, id string, password string) ([]byte, return key.ToEncryptedJSON(password, ks.scryptParams) } -func (ks *eth) Add(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +func (ks *eth) Add(ctx context.Context, address common.Address, chainID *big.Int) error { ks.lock.Lock() defer ks.lock.Unlock() _, found := ks.keyRing.Eth[address.Hex()] if !found { return ErrKeyNotFound } - return ks.addKey(ctx, address, chainID, qopts...) + return ks.addKey(ctx, nil, address, chainID) } // caller must hold lock! -func (ks *eth) addKey(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +// ds is optional, for transactions +func (ks *eth) addKey(ctx context.Context, ds sqlutil.DataSource, address common.Address, chainID *big.Int) error { + if ds == nil { + ds = ks.ds + } state := new(ethkey.State) sql := `INSERT INTO evm.key_states (address, disabled, evm_chain_id, created_at, updated_at) VALUES ($1, false, $2, NOW(), NOW()) RETURNING *;` - q := ks.q.WithOpts(qopts...) - q = q.WithOpts(pg.WithParentCtx(ctx)) - if err := q.Get(state, sql, address, chainID.String()); err != nil { - return errors.Wrap(err, "failed to insert evm_key_state") + if err := ds.GetContext(ctx, state, sql, address, chainID.String()); err != nil { + return errors.Wrap(err, "failed to insert key_state") } // consider: do we really need a cache of the keystates? ks.keyStates.add(state) @@ -210,24 +213,23 @@ func (ks *eth) addKey(ctx context.Context, address common.Address, chainID *big. return nil } -func (ks *eth) Enable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +func (ks *eth) Enable(ctx context.Context, address common.Address, chainID *big.Int) error { ks.lock.Lock() defer ks.lock.Unlock() _, found := ks.keyRing.Eth[address.Hex()] if !found { return ErrKeyNotFound } - return ks.enable(ctx, address, chainID, qopts...) + return ks.enable(ctx, address, chainID) } // caller must hold lock! -func (ks *eth) enable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +func (ks *eth) enable(ctx context.Context, address common.Address, chainID *big.Int) error { state := new(ethkey.State) - q := ks.q.WithOpts(qopts...) sql := `INSERT INTO evm.key_states as key_states ("address", "evm_chain_id", "disabled", "created_at", "updated_at") VALUES ($1, $2, false, NOW(), NOW()) ON CONFLICT ("address", "evm_chain_id") DO UPDATE SET "disabled" = false, "updated_at" = NOW() WHERE key_states."address" = $1 AND key_states."evm_chain_id" = $2 RETURNING *;` - if err := q.Get(state, sql, address, chainID.String()); err != nil { + if err := ks.ds.GetContext(ctx, state, sql, address, chainID.String()); err != nil { return errors.Wrap(err, "failed to enable state") } @@ -240,23 +242,22 @@ func (ks *eth) enable(ctx context.Context, address common.Address, chainID *big. return nil } -func (ks *eth) Disable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +func (ks *eth) Disable(ctx context.Context, address common.Address, chainID *big.Int) error { ks.lock.Lock() defer ks.lock.Unlock() _, found := ks.keyRing.Eth[address.Hex()] if !found { return errors.Errorf("no key exists with ID %s", address.Hex()) } - return ks.disable(ctx, address, chainID, qopts...) + return ks.disable(ctx, address, chainID) } -func (ks *eth) disable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { +func (ks *eth) disable(ctx context.Context, address common.Address, chainID *big.Int) error { state := new(ethkey.State) - q := ks.q.WithOpts(qopts...) sql := `INSERT INTO evm.key_states as key_states ("address", "evm_chain_id", "disabled", "created_at", "updated_at") VALUES ($1, $2, true, NOW(), NOW()) ON CONFLICT ("address", "evm_chain_id") DO UPDATE SET "disabled" = true, "updated_at" = NOW() WHERE key_states."address" = $1 AND key_states."evm_chain_id" = $2 RETURNING *;` - if err := q.Get(state, sql, address, chainID.String()); err != nil { + if err := ks.ds.GetContext(ctx, state, sql, address, chainID.String()); err != nil { return errors.Wrap(err, "failed to disable state") } @@ -279,8 +280,8 @@ func (ks *eth) Delete(ctx context.Context, id string) (ethkey.KeyV2, error) { if err != nil { return ethkey.KeyV2{}, err } - err = ks.safeRemoveKey(key, func(tx pg.Queryer) error { - _, err2 := tx.Exec(`DELETE FROM evm.key_states WHERE address = $1`, key.Address) + err = ks.safeRemoveKey(ctx, key, func(ds sqlutil.DataSource) error { + _, err2 := ds.ExecContext(ctx, `DELETE FROM evm.key_states WHERE address = $1`, key.Address) return err2 }) if err != nil { @@ -511,7 +512,7 @@ func (ks *eth) XXXTestingOnlySetState(ctx context.Context, state ethkey.State) { *existingState = state sql := `UPDATE evm.key_states SET address = :address, is_disabled = :is_disabled, evm_chain_id = :evm_chain_id, updated_at = NOW() WHERE address = :address;` - _, err := ks.q.NamedExec(sql, state) + _, err := ks.ds.NamedExecContext(ctx, sql, state) if err != nil { panic(err.Error()) } @@ -565,9 +566,9 @@ func (ks *eth) keysForChain(chainID *big.Int, includeDisabled bool) (keys []ethk // caller must hold lock! func (ks *eth) add(ctx context.Context, key ethkey.KeyV2, chainIDs ...*big.Int) (err error) { - err = ks.safeAddKey(key, func(tx pg.Queryer) (serr error) { + err = ks.safeAddKey(ctx, key, func(tx sqlutil.DataSource) (serr error) { for _, chainID := range chainIDs { - if serr = ks.addKey(ctx, key.Address, chainID, pg.WithQueryer(tx)); serr != nil { + if serr = ks.addKey(ctx, tx, key.Address, chainID); serr != nil { return serr } } diff --git a/core/services/keystore/eth_test.go b/core/services/keystore/eth_test.go index 6bc346bf4f8..07a41599f7d 100644 --- a/core/services/keystore/eth_test.go +++ b/core/services/keystore/eth_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "fmt" "math/big" "sort" @@ -12,13 +13,14 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" commonutils "github.com/smartcontractkit/chainlink-common/pkg/utils" evmclient "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" ubig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils/big" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" @@ -27,18 +29,20 @@ import ( func Test_EthKeyStore(t *testing.T) { t.Parallel() - db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) + db := sqlutil.WrapDataSource(pgtest.NewSqlxDB(t), logger.Test(t), sqlutil.TimeoutHook(func() time.Duration { + return 5 * time.Minute + }), sqlutil.MonitorHook(func() bool { return true })) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - err := keyStore.Unlock(cltest.Password) + keyStore := keystore.ExposedNewMaster(t, db) + err := keyStore.Unlock(testutils.Context(t), cltest.Password) require.NoError(t, err) ethKeyStore := keyStore.Eth() reset := func() { + ctx := context.Background() // Executed on cleanup keyStore.ResetXXXTestOnly() - require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) - require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM evm.key_states"))) - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, commonutils.JustError(db.ExecContext(ctx, "DELETE FROM encrypted_key_rings"))) + require.NoError(t, commonutils.JustError(db.ExecContext(ctx, "DELETE FROM evm.key_states"))) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } const statesTableName = "evm.key_states" @@ -58,11 +62,11 @@ func Test_EthKeyStore(t *testing.T) { cltest.AssertCount(t, db, statesTableName, 1) var state ethkey.State sql := fmt.Sprintf(`SELECT address, disabled, evm_chain_id, created_at, updated_at from %s LIMIT 1`, statesTableName) - require.NoError(t, db.Get(&state, sql)) + require.NoError(t, db.GetContext(ctx, &state, sql)) require.Equal(t, state.Address.Address(), retrievedKeys[0].Address) // adds key to db keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) retrievedKeys, err = ethKeyStore.GetAll(ctx) require.NoError(t, err) require.Equal(t, 1, len(retrievedKeys)) @@ -217,9 +221,8 @@ func Test_EthKeyStore_GetRoundRobinAddress(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() t.Run("should error when no addresses", func(t *testing.T) { @@ -341,8 +344,7 @@ func Test_EthKeyStore_SignTx(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - config := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) ethKeyStore := keyStore.Eth() k, _ := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -364,17 +366,17 @@ func Test_EthKeyStore_E2E(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - err := keyStore.Unlock(cltest.Password) + keyStore := keystore.ExposedNewMaster(t, db) + err := keyStore.Unlock(testutils.Context(t), cltest.Password) require.NoError(t, err) ks := keyStore.Eth() reset := func() { + ctx := testutils.Context(t) keyStore.ResetXXXTestOnly() require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) require.NoError(t, commonutils.JustError(db.Exec("DELETE FROM evm.key_states"))) - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -499,8 +501,7 @@ func Test_EthKeyStore_SubscribeToKeyChanges(t *testing.T) { chDone := make(chan struct{}) defer func() { close(chDone) }() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() chSub, unsubscribe := ks.SubscribeToKeyChanges(ctx) defer unsubscribe() @@ -567,8 +568,7 @@ func Test_EthKeyStore_Enable(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() t.Run("already existing disabled key gets enabled", func(t *testing.T) { @@ -618,8 +618,7 @@ func Test_EthKeyStore_EnsureKeys(t *testing.T) { t.Run("creates one unique key per chain if none exist", func(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() testutils.AssertCount(t, db, "evm.key_states", 0) @@ -634,8 +633,7 @@ func Test_EthKeyStore_EnsureKeys(t *testing.T) { t.Run("does nothing if a key exists for a chain", func(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() // Add one enabled key @@ -658,8 +656,7 @@ func Test_EthKeyStore_EnsureKeys(t *testing.T) { t.Run("does nothing if a key exists but is disabled for a chain", func(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() // Add one enabled key @@ -693,8 +690,7 @@ func Test_EthKeyStore_Delete(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() randKeyID := utils.RandomAddress().Hex() @@ -741,8 +737,7 @@ func Test_EthKeyStore_CheckEnabled(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() // create keys @@ -827,8 +822,7 @@ func Test_EthKeyStore_Disable(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) ks := keyStore.Eth() t.Run("creates key, deletes it unsafely and then enable creates it again", func(t *testing.T) { diff --git a/core/services/keystore/helpers_test.go b/core/services/keystore/helpers_test.go index d0b2a21ab38..e53e0af0c20 100644 --- a/core/services/keystore/helpers_test.go +++ b/core/services/keystore/helpers_test.go @@ -1,15 +1,14 @@ package keystore import ( + "context" "testing" "github.com/stretchr/testify/require" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -19,14 +18,14 @@ func mustNewEthKey(t *testing.T) *ethkey.KeyV2 { return &key } -func ExposedNewMaster(t *testing.T, db *sqlx.DB, cfg pg.QConfig) *master { - return newMaster(db, utils.FastScryptParams, logger.TestLogger(t), cfg) +func ExposedNewMaster(t *testing.T, ds sqlutil.DataSource) *master { + return newMaster(ds, utils.FastScryptParams, logger.TestLogger(t)) } -func (m *master) ExportedSave() error { +func (m *master) ExportedSave(ctx context.Context) error { m.lock.Lock() defer m.lock.Unlock() - return m.save() + return m.save(ctx) } func (m *master) ResetXXXTestOnly() { diff --git a/core/services/keystore/keystoretest.go b/core/services/keystore/keystoretest.go index 6efc8e76bcf..91dc87ffe95 100644 --- a/core/services/keystore/keystoretest.go +++ b/core/services/keystore/keystoretest.go @@ -1,13 +1,12 @@ package keystore import ( + "context" "errors" "sync" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -19,25 +18,25 @@ import ( // to support DB callbacks. type memoryORM struct { keyRing *encryptedKeyRing - q pg.Queryer + ds sqlutil.DataSource mu sync.RWMutex } -func (o *memoryORM) isEmpty() (bool, error) { +func (o *memoryORM) isEmpty(ctx context.Context) (bool, error) { return false, nil } -func (o *memoryORM) saveEncryptedKeyRing(kr *encryptedKeyRing, callbacks ...func(pg.Queryer) error) (err error) { +func (o *memoryORM) saveEncryptedKeyRing(ctx context.Context, kr *encryptedKeyRing, callbacks ...func(sqlutil.DataSource) error) (err error) { o.mu.Lock() defer o.mu.Unlock() o.keyRing = kr for _, c := range callbacks { - err = errors.Join(err, c(o.q)) + err = errors.Join(err, c(o.ds)) } return } -func (o *memoryORM) getEncryptedKeyRing() (encryptedKeyRing, error) { +func (o *memoryORM) getEncryptedKeyRing(ctx context.Context) (encryptedKeyRing, error) { o.mu.RLock() defer o.mu.RUnlock() if o.keyRing == nil { @@ -46,15 +45,15 @@ func (o *memoryORM) getEncryptedKeyRing() (encryptedKeyRing, error) { return *o.keyRing, nil } -func newInMemoryORM(q pg.Queryer) *memoryORM { - return &memoryORM{q: q} +func newInMemoryORM(ds sqlutil.DataSource) *memoryORM { + return &memoryORM{ds: ds} } // NewInMemory sets up a keystore which NOOPs attempts to access the `encrypted_key_rings` table. Accessing `evm.key_states` // will still hit the DB. -func NewInMemory(db *sqlx.DB, scryptParams utils.ScryptParams, lggr logger.Logger, cfg pg.QConfig) *master { - dbORM := NewORM(db, lggr, cfg) - memoryORM := newInMemoryORM(dbORM.q) +func NewInMemory(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr logger.Logger) *master { + dbORM := NewORM(ds, lggr) + memoryORM := newInMemoryORM(ds) km := &keyManager{ orm: memoryORM, @@ -68,7 +67,7 @@ func NewInMemory(db *sqlx.DB, scryptParams utils.ScryptParams, lggr logger.Logge keyManager: km, cosmos: newCosmosKeyStore(km), csa: newCSAKeyStore(km), - eth: newEthKeyStore(km, dbORM, dbORM.q), + eth: newEthKeyStore(km, dbORM, ds), ocr: newOCRKeyStore(km), ocr2: newOCR2KeyStore(km), p2p: newP2PKeyStore(km), diff --git a/core/services/keystore/master.go b/core/services/keystore/master.go index 05f19495f9d..bb5b21a96f0 100644 --- a/core/services/keystore/master.go +++ b/core/services/keystore/master.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "math/big" "reflect" @@ -8,8 +9,7 @@ import ( "github.com/pkg/errors" - "github.com/jmoiron/sqlx" - + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" @@ -22,7 +22,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" "github.com/smartcontractkit/chainlink/v2/core/utils" ) @@ -50,8 +49,8 @@ type Master interface { Cosmos() Cosmos StarkNet() StarkNet VRF() VRF - Unlock(password string) error - IsEmpty() (bool, error) + Unlock(ctx context.Context, password string) error + IsEmpty(ctx context.Context) (bool, error) } type master struct { @@ -69,12 +68,12 @@ type master struct { dkgEncrypt *dkgEncrypt } -func New(db *sqlx.DB, scryptParams utils.ScryptParams, lggr logger.Logger, cfg pg.QConfig) Master { - return newMaster(db, scryptParams, lggr, cfg) +func New(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr logger.Logger) Master { + return newMaster(ds, scryptParams, lggr) } -func newMaster(db *sqlx.DB, scryptParams utils.ScryptParams, lggr logger.Logger, cfg pg.QConfig) *master { - orm := NewORM(db, lggr, cfg) +func newMaster(ds sqlutil.DataSource, scryptParams utils.ScryptParams, lggr logger.Logger) *master { + orm := NewORM(ds, lggr) km := &keyManager{ orm: orm, keystateORM: orm, @@ -87,7 +86,7 @@ func newMaster(db *sqlx.DB, scryptParams utils.ScryptParams, lggr logger.Logger, keyManager: km, cosmos: newCosmosKeyStore(km), csa: newCSAKeyStore(km), - eth: newEthKeyStore(km, orm, orm.q), + eth: newEthKeyStore(km, orm, orm.ds), ocr: newOCRKeyStore(km), ocr2: newOCR2KeyStore(km), p2p: newP2PKeyStore(km), @@ -144,13 +143,13 @@ func (ks *master) VRF() VRF { } type ORM interface { - isEmpty() (bool, error) - saveEncryptedKeyRing(*encryptedKeyRing, ...func(pg.Queryer) error) error - getEncryptedKeyRing() (encryptedKeyRing, error) + isEmpty(context.Context) (bool, error) + saveEncryptedKeyRing(context.Context, *encryptedKeyRing, ...func(sqlutil.DataSource) error) error + getEncryptedKeyRing(context.Context) (encryptedKeyRing, error) } type keystateORM interface { - loadKeyStates() (*keyStates, error) + loadKeyStates(context.Context) (*keyStates, error) } type keyManager struct { @@ -164,11 +163,11 @@ type keyManager struct { logger logger.Logger } -func (km *keyManager) IsEmpty() (bool, error) { - return km.orm.isEmpty() +func (km *keyManager) IsEmpty(ctx context.Context) (bool, error) { + return km.orm.isEmpty(ctx) } -func (km *keyManager) Unlock(password string) error { +func (km *keyManager) Unlock(ctx context.Context, password string) error { km.lock.Lock() defer km.lock.Unlock() // DEV: allow Unlock() to be idempotent - this is especially useful in tests, @@ -178,7 +177,7 @@ func (km *keyManager) Unlock(password string) error { } return nil } - ekr, err := km.orm.getEncryptedKeyRing() + ekr, err := km.orm.getEncryptedKeyRing(ctx) if err != nil { return errors.Wrap(err, "unable to get encrypted key ring") } @@ -189,7 +188,7 @@ func (km *keyManager) Unlock(password string) error { kr.logPubKeys(km.logger) km.keyRing = kr - ks, err := km.keystateORM.loadKeyStates() + ks, err := km.keystateORM.loadKeyStates(ctx) if err != nil { return errors.Wrap(err, "unable to load key states") } @@ -200,16 +199,16 @@ func (km *keyManager) Unlock(password string) error { } // caller must hold lock! -func (km *keyManager) save(callbacks ...func(pg.Queryer) error) error { +func (km *keyManager) save(ctx context.Context, callbacks ...func(sqlutil.DataSource) error) error { ekb, err := km.keyRing.Encrypt(km.password, km.scryptParams) if err != nil { return errors.Wrap(err, "unable to encrypt keyRing") } - return km.orm.saveEncryptedKeyRing(&ekb, callbacks...) + return km.orm.saveEncryptedKeyRing(ctx, &ekb, callbacks...) } // caller must hold lock! -func (km *keyManager) safeAddKey(unknownKey Key, callbacks ...func(pg.Queryer) error) error { +func (km *keyManager) safeAddKey(ctx context.Context, unknownKey Key, callbacks ...func(sqlutil.DataSource) error) error { fieldName, err := GetFieldNameForKey(unknownKey) if err != nil { return err @@ -221,7 +220,7 @@ func (km *keyManager) safeAddKey(unknownKey Key, callbacks ...func(pg.Queryer) e keyMap := keyRing.FieldByName(fieldName) keyMap.SetMapIndex(id, key) // save keyring to DB - err = km.save(callbacks...) + err = km.save(ctx, callbacks...) // if save fails, remove key from keyring if err != nil { keyMap.SetMapIndex(id, reflect.Value{}) @@ -231,7 +230,7 @@ func (km *keyManager) safeAddKey(unknownKey Key, callbacks ...func(pg.Queryer) e } // caller must hold lock! -func (km *keyManager) safeRemoveKey(unknownKey Key, callbacks ...func(pg.Queryer) error) (err error) { +func (km *keyManager) safeRemoveKey(ctx context.Context, unknownKey Key, callbacks ...func(sqlutil.DataSource) error) (err error) { fieldName, err := GetFieldNameForKey(unknownKey) if err != nil { return err @@ -242,7 +241,7 @@ func (km *keyManager) safeRemoveKey(unknownKey Key, callbacks ...func(pg.Queryer keyMap := keyRing.FieldByName(fieldName) keyMap.SetMapIndex(id, reflect.Value{}) // save keyring to DB - err = km.save(callbacks...) + err = km.save(ctx, callbacks...) // if save fails, add key back to keyRing if err != nil { keyMap.SetMapIndex(id, key) diff --git a/core/services/keystore/master_test.go b/core/services/keystore/master_test.go index 73f636c6625..e41a7a771ae 100644 --- a/core/services/keystore/master_test.go +++ b/core/services/keystore/master_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" ) @@ -16,9 +16,8 @@ func TestMasterKeystore_Unlock_Save(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) + keyStore := keystore.ExposedNewMaster(t, db) const tableName = "encrypted_key_rings" reset := func() { keyStore.ResetXXXTestOnly() @@ -28,36 +27,40 @@ func TestMasterKeystore_Unlock_Save(t *testing.T) { t.Run("can be unlocked more than once, as long as the passwords match", func(t *testing.T) { defer reset() - require.NoError(t, keyStore.Unlock(cltest.Password)) - require.NoError(t, keyStore.Unlock(cltest.Password)) - require.NoError(t, keyStore.Unlock(cltest.Password)) - require.Error(t, keyStore.Unlock("wrong password")) + ctx := testutils.Context(t) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + require.Error(t, keyStore.Unlock(ctx, "wrong password")) }) t.Run("saves an empty keyRing", func(t *testing.T) { defer reset() - require.NoError(t, keyStore.Unlock(cltest.Password)) + ctx := testutils.Context(t) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) cltest.AssertCount(t, db, tableName, 1) - require.NoError(t, keyStore.ExportedSave()) + require.NoError(t, keyStore.ExportedSave(ctx)) cltest.AssertCount(t, db, tableName, 1) }) t.Run("won't load a saved keyRing if the password is incorrect", func(t *testing.T) { defer reset() - require.NoError(t, keyStore.Unlock(cltest.Password)) + ctx := testutils.Context(t) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) cltest.MustInsertRandomKey(t, keyStore.Eth()) // need at least 1 key to encrypt cltest.AssertCount(t, db, tableName, 1) keyStore.ResetXXXTestOnly() cltest.AssertCount(t, db, tableName, 1) - require.Error(t, keyStore.Unlock("password2")) + require.Error(t, keyStore.Unlock(ctx, "password2")) cltest.AssertCount(t, db, tableName, 1) }) t.Run("loads a saved keyRing if the password is correct", func(t *testing.T) { defer reset() - require.NoError(t, keyStore.Unlock(cltest.Password)) - require.NoError(t, keyStore.ExportedSave()) + ctx := testutils.Context(t) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) + require.NoError(t, keyStore.ExportedSave(ctx)) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) }) } diff --git a/core/services/keystore/mocks/cosmos.go b/core/services/keystore/mocks/cosmos.go index 40ba12d15d7..36d1daec524 100644 --- a/core/services/keystore/mocks/cosmos.go +++ b/core/services/keystore/mocks/cosmos.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + cosmoskey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/cosmoskey" mock "github.com/stretchr/testify/mock" @@ -13,17 +15,17 @@ type Cosmos struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *Cosmos) Add(key cosmoskey.Key) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *Cosmos) Add(ctx context.Context, key cosmoskey.Key) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(cosmoskey.Key) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, cosmoskey.Key) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -31,9 +33,9 @@ func (_m *Cosmos) Add(key cosmoskey.Key) error { return r0 } -// Create provides a mock function with given fields: -func (_m *Cosmos) Create() (cosmoskey.Key, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *Cosmos) Create(ctx context.Context) (cosmoskey.Key, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -41,17 +43,17 @@ func (_m *Cosmos) Create() (cosmoskey.Key, error) { var r0 cosmoskey.Key var r1 error - if rf, ok := ret.Get(0).(func() (cosmoskey.Key, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (cosmoskey.Key, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() cosmoskey.Key); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) cosmoskey.Key); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(cosmoskey.Key) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -59,9 +61,9 @@ func (_m *Cosmos) Create() (cosmoskey.Key, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *Cosmos) Delete(id string) (cosmoskey.Key, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *Cosmos) Delete(ctx context.Context, id string) (cosmoskey.Key, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -69,17 +71,17 @@ func (_m *Cosmos) Delete(id string) (cosmoskey.Key, error) { var r0 cosmoskey.Key var r1 error - if rf, ok := ret.Get(0).(func(string) (cosmoskey.Key, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (cosmoskey.Key, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) cosmoskey.Key); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) cosmoskey.Key); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(cosmoskey.Key) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -87,17 +89,17 @@ func (_m *Cosmos) Delete(id string) (cosmoskey.Key, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *Cosmos) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *Cosmos) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -193,9 +195,9 @@ func (_m *Cosmos) GetAll() ([]cosmoskey.Key, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *Cosmos) Import(keyJSON []byte, password string) (cosmoskey.Key, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *Cosmos) Import(ctx context.Context, keyJSON []byte, password string) (cosmoskey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -203,17 +205,17 @@ func (_m *Cosmos) Import(keyJSON []byte, password string) (cosmoskey.Key, error) var r0 cosmoskey.Key var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (cosmoskey.Key, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (cosmoskey.Key, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) cosmoskey.Key); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) cosmoskey.Key); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(cosmoskey.Key) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/csa.go b/core/services/keystore/mocks/csa.go index ad5b25a27bd..ba0ce76e39a 100644 --- a/core/services/keystore/mocks/csa.go +++ b/core/services/keystore/mocks/csa.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + csakey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" mock "github.com/stretchr/testify/mock" @@ -13,17 +15,17 @@ type CSA struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *CSA) Add(key csakey.KeyV2) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *CSA) Add(ctx context.Context, key csakey.KeyV2) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(csakey.KeyV2) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, csakey.KeyV2) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -31,9 +33,9 @@ func (_m *CSA) Add(key csakey.KeyV2) error { return r0 } -// Create provides a mock function with given fields: -func (_m *CSA) Create() (csakey.KeyV2, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *CSA) Create(ctx context.Context) (csakey.KeyV2, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -41,17 +43,17 @@ func (_m *CSA) Create() (csakey.KeyV2, error) { var r0 csakey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func() (csakey.KeyV2, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (csakey.KeyV2, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() csakey.KeyV2); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) csakey.KeyV2); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(csakey.KeyV2) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -59,9 +61,9 @@ func (_m *CSA) Create() (csakey.KeyV2, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *CSA) Delete(id string) (csakey.KeyV2, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *CSA) Delete(ctx context.Context, id string) (csakey.KeyV2, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -69,17 +71,17 @@ func (_m *CSA) Delete(id string) (csakey.KeyV2, error) { var r0 csakey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func(string) (csakey.KeyV2, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (csakey.KeyV2, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) csakey.KeyV2); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) csakey.KeyV2); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(csakey.KeyV2) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -87,17 +89,17 @@ func (_m *CSA) Delete(id string) (csakey.KeyV2, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *CSA) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *CSA) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -193,9 +195,9 @@ func (_m *CSA) GetAll() ([]csakey.KeyV2, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *CSA) Import(keyJSON []byte, password string) (csakey.KeyV2, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *CSA) Import(ctx context.Context, keyJSON []byte, password string) (csakey.KeyV2, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -203,17 +205,17 @@ func (_m *CSA) Import(keyJSON []byte, password string) (csakey.KeyV2, error) { var r0 csakey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (csakey.KeyV2, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (csakey.KeyV2, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) csakey.KeyV2); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) csakey.KeyV2); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(csakey.KeyV2) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/dkg_encrypt.go b/core/services/keystore/mocks/dkg_encrypt.go index e7e52bada25..1dc17b61183 100644 --- a/core/services/keystore/mocks/dkg_encrypt.go +++ b/core/services/keystore/mocks/dkg_encrypt.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + dkgencryptkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgencryptkey" mock "github.com/stretchr/testify/mock" @@ -13,17 +15,17 @@ type DKGEncrypt struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *DKGEncrypt) Add(key dkgencryptkey.Key) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *DKGEncrypt) Add(ctx context.Context, key dkgencryptkey.Key) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(dkgencryptkey.Key) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, dkgencryptkey.Key) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -31,9 +33,9 @@ func (_m *DKGEncrypt) Add(key dkgencryptkey.Key) error { return r0 } -// Create provides a mock function with given fields: -func (_m *DKGEncrypt) Create() (dkgencryptkey.Key, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *DKGEncrypt) Create(ctx context.Context) (dkgencryptkey.Key, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -41,17 +43,17 @@ func (_m *DKGEncrypt) Create() (dkgencryptkey.Key, error) { var r0 dkgencryptkey.Key var r1 error - if rf, ok := ret.Get(0).(func() (dkgencryptkey.Key, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (dkgencryptkey.Key, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() dkgencryptkey.Key); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) dkgencryptkey.Key); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(dkgencryptkey.Key) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -59,9 +61,9 @@ func (_m *DKGEncrypt) Create() (dkgencryptkey.Key, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *DKGEncrypt) Delete(id string) (dkgencryptkey.Key, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *DKGEncrypt) Delete(ctx context.Context, id string) (dkgencryptkey.Key, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -69,17 +71,17 @@ func (_m *DKGEncrypt) Delete(id string) (dkgencryptkey.Key, error) { var r0 dkgencryptkey.Key var r1 error - if rf, ok := ret.Get(0).(func(string) (dkgencryptkey.Key, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (dkgencryptkey.Key, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) dkgencryptkey.Key); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) dkgencryptkey.Key); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(dkgencryptkey.Key) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -87,17 +89,17 @@ func (_m *DKGEncrypt) Delete(id string) (dkgencryptkey.Key, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *DKGEncrypt) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *DKGEncrypt) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -193,9 +195,9 @@ func (_m *DKGEncrypt) GetAll() ([]dkgencryptkey.Key, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *DKGEncrypt) Import(keyJSON []byte, password string) (dkgencryptkey.Key, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *DKGEncrypt) Import(ctx context.Context, keyJSON []byte, password string) (dkgencryptkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -203,17 +205,17 @@ func (_m *DKGEncrypt) Import(keyJSON []byte, password string) (dkgencryptkey.Key var r0 dkgencryptkey.Key var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (dkgencryptkey.Key, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (dkgencryptkey.Key, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) dkgencryptkey.Key); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) dkgencryptkey.Key); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(dkgencryptkey.Key) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/dkg_sign.go b/core/services/keystore/mocks/dkg_sign.go index e5c6434d90d..1ff71e2fc8d 100644 --- a/core/services/keystore/mocks/dkg_sign.go +++ b/core/services/keystore/mocks/dkg_sign.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + dkgsignkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/dkgsignkey" mock "github.com/stretchr/testify/mock" @@ -13,17 +15,17 @@ type DKGSign struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *DKGSign) Add(key dkgsignkey.Key) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *DKGSign) Add(ctx context.Context, key dkgsignkey.Key) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(dkgsignkey.Key) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, dkgsignkey.Key) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -31,9 +33,9 @@ func (_m *DKGSign) Add(key dkgsignkey.Key) error { return r0 } -// Create provides a mock function with given fields: -func (_m *DKGSign) Create() (dkgsignkey.Key, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *DKGSign) Create(ctx context.Context) (dkgsignkey.Key, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -41,17 +43,17 @@ func (_m *DKGSign) Create() (dkgsignkey.Key, error) { var r0 dkgsignkey.Key var r1 error - if rf, ok := ret.Get(0).(func() (dkgsignkey.Key, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (dkgsignkey.Key, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() dkgsignkey.Key); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) dkgsignkey.Key); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(dkgsignkey.Key) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -59,9 +61,9 @@ func (_m *DKGSign) Create() (dkgsignkey.Key, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *DKGSign) Delete(id string) (dkgsignkey.Key, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *DKGSign) Delete(ctx context.Context, id string) (dkgsignkey.Key, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -69,17 +71,17 @@ func (_m *DKGSign) Delete(id string) (dkgsignkey.Key, error) { var r0 dkgsignkey.Key var r1 error - if rf, ok := ret.Get(0).(func(string) (dkgsignkey.Key, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (dkgsignkey.Key, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) dkgsignkey.Key); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) dkgsignkey.Key); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(dkgsignkey.Key) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -87,17 +89,17 @@ func (_m *DKGSign) Delete(id string) (dkgsignkey.Key, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *DKGSign) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *DKGSign) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -193,9 +195,9 @@ func (_m *DKGSign) GetAll() ([]dkgsignkey.Key, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *DKGSign) Import(keyJSON []byte, password string) (dkgsignkey.Key, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *DKGSign) Import(ctx context.Context, keyJSON []byte, password string) (dkgsignkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -203,17 +205,17 @@ func (_m *DKGSign) Import(keyJSON []byte, password string) (dkgsignkey.Key, erro var r0 dkgsignkey.Key var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (dkgsignkey.Key, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (dkgsignkey.Key, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) dkgsignkey.Key); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) dkgsignkey.Key); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(dkgsignkey.Key) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/eth.go b/core/services/keystore/mocks/eth.go index a5dd612d9e5..591477ce6d3 100644 --- a/core/services/keystore/mocks/eth.go +++ b/core/services/keystore/mocks/eth.go @@ -12,8 +12,6 @@ import ( mock "github.com/stretchr/testify/mock" - pg "github.com/smartcontractkit/chainlink/v2/core/services/pg" - types "github.com/ethereum/go-ethereum/core/types" ) @@ -22,24 +20,17 @@ type Eth struct { mock.Mock } -// Add provides a mock function with given fields: ctx, address, chainID, qopts -func (_m *Eth) Add(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, address, chainID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// Add provides a mock function with given fields: ctx, address, chainID +func (_m *Eth) Add(ctx context.Context, address common.Address, chainID *big.Int) error { + ret := _m.Called(ctx, address, chainID) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, ...pg.QOpt) error); ok { - r0 = rf(ctx, address, chainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) error); ok { + r0 = rf(ctx, address, chainID) } else { r0 = ret.Error(0) } @@ -128,24 +119,17 @@ func (_m *Eth) Delete(ctx context.Context, id string) (ethkey.KeyV2, error) { return r0, r1 } -// Disable provides a mock function with given fields: ctx, address, chainID, qopts -func (_m *Eth) Disable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, address, chainID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// Disable provides a mock function with given fields: ctx, address, chainID +func (_m *Eth) Disable(ctx context.Context, address common.Address, chainID *big.Int) error { + ret := _m.Called(ctx, address, chainID) if len(ret) == 0 { panic("no return value specified for Disable") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, ...pg.QOpt) error); ok { - r0 = rf(ctx, address, chainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) error); ok { + r0 = rf(ctx, address, chainID) } else { r0 = ret.Error(0) } @@ -153,24 +137,17 @@ func (_m *Eth) Disable(ctx context.Context, address common.Address, chainID *big return r0 } -// Enable provides a mock function with given fields: ctx, address, chainID, qopts -func (_m *Eth) Enable(ctx context.Context, address common.Address, chainID *big.Int, qopts ...pg.QOpt) error { - _va := make([]interface{}, len(qopts)) - for _i := range qopts { - _va[_i] = qopts[_i] - } - var _ca []interface{} - _ca = append(_ca, ctx, address, chainID) - _ca = append(_ca, _va...) - ret := _m.Called(_ca...) +// Enable provides a mock function with given fields: ctx, address, chainID +func (_m *Eth) Enable(ctx context.Context, address common.Address, chainID *big.Int) error { + ret := _m.Called(ctx, address, chainID) if len(ret) == 0 { panic("no return value specified for Enable") } var r0 error - if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int, ...pg.QOpt) error); ok { - r0 = rf(ctx, address, chainID, qopts...) + if rf, ok := ret.Get(0).(func(context.Context, common.Address, *big.Int) error); ok { + r0 = rf(ctx, address, chainID) } else { r0 = ret.Error(0) } diff --git a/core/services/keystore/mocks/master.go b/core/services/keystore/mocks/master.go index 3025f5b103a..4662635cb00 100644 --- a/core/services/keystore/mocks/master.go +++ b/core/services/keystore/mocks/master.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + keystore "github.com/smartcontractkit/chainlink/v2/core/services/keystore" mock "github.com/stretchr/testify/mock" ) @@ -112,9 +114,9 @@ func (_m *Master) Eth() keystore.Eth { return r0 } -// IsEmpty provides a mock function with given fields: -func (_m *Master) IsEmpty() (bool, error) { - ret := _m.Called() +// IsEmpty provides a mock function with given fields: ctx +func (_m *Master) IsEmpty(ctx context.Context) (bool, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for IsEmpty") @@ -122,17 +124,17 @@ func (_m *Master) IsEmpty() (bool, error) { var r0 bool var r1 error - if rf, ok := ret.Get(0).(func() (bool, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (bool, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() bool); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) bool); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(bool) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -240,17 +242,17 @@ func (_m *Master) StarkNet() keystore.StarkNet { return r0 } -// Unlock provides a mock function with given fields: password -func (_m *Master) Unlock(password string) error { - ret := _m.Called(password) +// Unlock provides a mock function with given fields: ctx, password +func (_m *Master) Unlock(ctx context.Context, password string) error { + ret := _m.Called(ctx, password) if len(ret) == 0 { panic("no return value specified for Unlock") } var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(password) + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, password) } else { r0 = ret.Error(0) } diff --git a/core/services/keystore/mocks/ocr.go b/core/services/keystore/mocks/ocr.go index e1c4d588330..b29f07f03f4 100644 --- a/core/services/keystore/mocks/ocr.go +++ b/core/services/keystore/mocks/ocr.go @@ -3,8 +3,11 @@ package mocks import ( - ocrkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" + context "context" + mock "github.com/stretchr/testify/mock" + + ocrkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" ) // OCR is an autogenerated mock type for the OCR type @@ -12,17 +15,17 @@ type OCR struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *OCR) Add(key ocrkey.KeyV2) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *OCR) Add(ctx context.Context, key ocrkey.KeyV2) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(ocrkey.KeyV2) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, ocrkey.KeyV2) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -30,9 +33,9 @@ func (_m *OCR) Add(key ocrkey.KeyV2) error { return r0 } -// Create provides a mock function with given fields: -func (_m *OCR) Create() (ocrkey.KeyV2, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *OCR) Create(ctx context.Context) (ocrkey.KeyV2, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -40,17 +43,17 @@ func (_m *OCR) Create() (ocrkey.KeyV2, error) { var r0 ocrkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func() (ocrkey.KeyV2, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (ocrkey.KeyV2, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() ocrkey.KeyV2); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) ocrkey.KeyV2); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(ocrkey.KeyV2) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -58,9 +61,9 @@ func (_m *OCR) Create() (ocrkey.KeyV2, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *OCR) Delete(id string) (ocrkey.KeyV2, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *OCR) Delete(ctx context.Context, id string) (ocrkey.KeyV2, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -68,17 +71,17 @@ func (_m *OCR) Delete(id string) (ocrkey.KeyV2, error) { var r0 ocrkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func(string) (ocrkey.KeyV2, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (ocrkey.KeyV2, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) ocrkey.KeyV2); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) ocrkey.KeyV2); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(ocrkey.KeyV2) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -86,17 +89,17 @@ func (_m *OCR) Delete(id string) (ocrkey.KeyV2, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *OCR) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *OCR) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -192,9 +195,9 @@ func (_m *OCR) GetAll() ([]ocrkey.KeyV2, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *OCR) Import(keyJSON []byte, password string) (ocrkey.KeyV2, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *OCR) Import(ctx context.Context, keyJSON []byte, password string) (ocrkey.KeyV2, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -202,17 +205,17 @@ func (_m *OCR) Import(keyJSON []byte, password string) (ocrkey.KeyV2, error) { var r0 ocrkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (ocrkey.KeyV2, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (ocrkey.KeyV2, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) ocrkey.KeyV2); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) ocrkey.KeyV2); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(ocrkey.KeyV2) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/ocr2.go b/core/services/keystore/mocks/ocr2.go index d44e739deed..13f0c65b9d1 100644 --- a/core/services/keystore/mocks/ocr2.go +++ b/core/services/keystore/mocks/ocr2.go @@ -3,6 +3,8 @@ package mocks import ( + context "context" + chaintype "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" mock "github.com/stretchr/testify/mock" @@ -15,17 +17,17 @@ type OCR2 struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *OCR2) Add(key ocr2key.KeyBundle) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *OCR2) Add(ctx context.Context, key ocr2key.KeyBundle) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(ocr2key.KeyBundle) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, ocr2key.KeyBundle) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -33,9 +35,9 @@ func (_m *OCR2) Add(key ocr2key.KeyBundle) error { return r0 } -// Create provides a mock function with given fields: _a0 -func (_m *OCR2) Create(_a0 chaintype.ChainType) (ocr2key.KeyBundle, error) { - ret := _m.Called(_a0) +// Create provides a mock function with given fields: _a0, _a1 +func (_m *OCR2) Create(_a0 context.Context, _a1 chaintype.ChainType) (ocr2key.KeyBundle, error) { + ret := _m.Called(_a0, _a1) if len(ret) == 0 { panic("no return value specified for Create") @@ -43,19 +45,19 @@ func (_m *OCR2) Create(_a0 chaintype.ChainType) (ocr2key.KeyBundle, error) { var r0 ocr2key.KeyBundle var r1 error - if rf, ok := ret.Get(0).(func(chaintype.ChainType) (ocr2key.KeyBundle, error)); ok { - return rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, chaintype.ChainType) (ocr2key.KeyBundle, error)); ok { + return rf(_a0, _a1) } - if rf, ok := ret.Get(0).(func(chaintype.ChainType) ocr2key.KeyBundle); ok { - r0 = rf(_a0) + if rf, ok := ret.Get(0).(func(context.Context, chaintype.ChainType) ocr2key.KeyBundle); ok { + r0 = rf(_a0, _a1) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(ocr2key.KeyBundle) } } - if rf, ok := ret.Get(1).(func(chaintype.ChainType) error); ok { - r1 = rf(_a0) + if rf, ok := ret.Get(1).(func(context.Context, chaintype.ChainType) error); ok { + r1 = rf(_a0, _a1) } else { r1 = ret.Error(1) } @@ -63,17 +65,17 @@ func (_m *OCR2) Create(_a0 chaintype.ChainType) (ocr2key.KeyBundle, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *OCR2) Delete(id string) error { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *OCR2) Delete(ctx context.Context, id string) error { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") } var r0 error - if rf, ok := ret.Get(0).(func(string) error); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, id) } else { r0 = ret.Error(0) } @@ -81,13 +83,14 @@ func (_m *OCR2) Delete(id string) error { return r0 } -// EnsureKeys provides a mock function with given fields: enabledChains -func (_m *OCR2) EnsureKeys(enabledChains ...chaintype.ChainType) error { +// EnsureKeys provides a mock function with given fields: ctx, enabledChains +func (_m *OCR2) EnsureKeys(ctx context.Context, enabledChains ...chaintype.ChainType) error { _va := make([]interface{}, len(enabledChains)) for _i := range enabledChains { _va[_i] = enabledChains[_i] } var _ca []interface{} + _ca = append(_ca, ctx) _ca = append(_ca, _va...) ret := _m.Called(_ca...) @@ -96,8 +99,8 @@ func (_m *OCR2) EnsureKeys(enabledChains ...chaintype.ChainType) error { } var r0 error - if rf, ok := ret.Get(0).(func(...chaintype.ChainType) error); ok { - r0 = rf(enabledChains...) + if rf, ok := ret.Get(0).(func(context.Context, ...chaintype.ChainType) error); ok { + r0 = rf(ctx, enabledChains...) } else { r0 = ret.Error(0) } @@ -225,9 +228,9 @@ func (_m *OCR2) GetAllOfType(_a0 chaintype.ChainType) ([]ocr2key.KeyBundle, erro return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *OCR2) Import(keyJSON []byte, password string) (ocr2key.KeyBundle, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *OCR2) Import(ctx context.Context, keyJSON []byte, password string) (ocr2key.KeyBundle, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -235,19 +238,19 @@ func (_m *OCR2) Import(keyJSON []byte, password string) (ocr2key.KeyBundle, erro var r0 ocr2key.KeyBundle var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (ocr2key.KeyBundle, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (ocr2key.KeyBundle, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) ocr2key.KeyBundle); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) ocr2key.KeyBundle); ok { + r0 = rf(ctx, keyJSON, password) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(ocr2key.KeyBundle) } } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/p2p.go b/core/services/keystore/mocks/p2p.go index fa2a1b6ceeb..7e480c5d96f 100644 --- a/core/services/keystore/mocks/p2p.go +++ b/core/services/keystore/mocks/p2p.go @@ -3,8 +3,11 @@ package mocks import ( - p2pkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" + context "context" + mock "github.com/stretchr/testify/mock" + + p2pkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" ) // P2P is an autogenerated mock type for the P2P type @@ -12,17 +15,17 @@ type P2P struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *P2P) Add(key p2pkey.KeyV2) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *P2P) Add(ctx context.Context, key p2pkey.KeyV2) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(p2pkey.KeyV2) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, p2pkey.KeyV2) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -30,9 +33,9 @@ func (_m *P2P) Add(key p2pkey.KeyV2) error { return r0 } -// Create provides a mock function with given fields: -func (_m *P2P) Create() (p2pkey.KeyV2, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *P2P) Create(ctx context.Context) (p2pkey.KeyV2, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -40,17 +43,17 @@ func (_m *P2P) Create() (p2pkey.KeyV2, error) { var r0 p2pkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func() (p2pkey.KeyV2, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (p2pkey.KeyV2, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() p2pkey.KeyV2); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) p2pkey.KeyV2); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(p2pkey.KeyV2) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -58,9 +61,9 @@ func (_m *P2P) Create() (p2pkey.KeyV2, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *P2P) Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *P2P) Delete(ctx context.Context, id p2pkey.PeerID) (p2pkey.KeyV2, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -68,17 +71,17 @@ func (_m *P2P) Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) { var r0 p2pkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func(p2pkey.PeerID) (p2pkey.KeyV2, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, p2pkey.PeerID) (p2pkey.KeyV2, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(p2pkey.PeerID) p2pkey.KeyV2); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, p2pkey.PeerID) p2pkey.KeyV2); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(p2pkey.KeyV2) } - if rf, ok := ret.Get(1).(func(p2pkey.PeerID) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, p2pkey.PeerID) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -86,17 +89,17 @@ func (_m *P2P) Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *P2P) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *P2P) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -220,9 +223,9 @@ func (_m *P2P) GetOrFirst(id p2pkey.PeerID) (p2pkey.KeyV2, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *P2P) Import(keyJSON []byte, password string) (p2pkey.KeyV2, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *P2P) Import(ctx context.Context, keyJSON []byte, password string) (p2pkey.KeyV2, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -230,17 +233,17 @@ func (_m *P2P) Import(keyJSON []byte, password string) (p2pkey.KeyV2, error) { var r0 p2pkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (p2pkey.KeyV2, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (p2pkey.KeyV2, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) p2pkey.KeyV2); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) p2pkey.KeyV2); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(p2pkey.KeyV2) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/solana.go b/core/services/keystore/mocks/solana.go index c2cc4139bab..7c4593ac5a3 100644 --- a/core/services/keystore/mocks/solana.go +++ b/core/services/keystore/mocks/solana.go @@ -15,17 +15,17 @@ type Solana struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *Solana) Add(key solkey.Key) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *Solana) Add(ctx context.Context, key solkey.Key) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(solkey.Key) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, solkey.Key) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -33,9 +33,9 @@ func (_m *Solana) Add(key solkey.Key) error { return r0 } -// Create provides a mock function with given fields: -func (_m *Solana) Create() (solkey.Key, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *Solana) Create(ctx context.Context) (solkey.Key, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -43,17 +43,17 @@ func (_m *Solana) Create() (solkey.Key, error) { var r0 solkey.Key var r1 error - if rf, ok := ret.Get(0).(func() (solkey.Key, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (solkey.Key, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() solkey.Key); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) solkey.Key); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(solkey.Key) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -61,9 +61,9 @@ func (_m *Solana) Create() (solkey.Key, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *Solana) Delete(id string) (solkey.Key, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *Solana) Delete(ctx context.Context, id string) (solkey.Key, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -71,17 +71,17 @@ func (_m *Solana) Delete(id string) (solkey.Key, error) { var r0 solkey.Key var r1 error - if rf, ok := ret.Get(0).(func(string) (solkey.Key, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (solkey.Key, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) solkey.Key); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) solkey.Key); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(solkey.Key) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -89,17 +89,17 @@ func (_m *Solana) Delete(id string) (solkey.Key, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *Solana) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *Solana) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -195,9 +195,9 @@ func (_m *Solana) GetAll() ([]solkey.Key, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *Solana) Import(keyJSON []byte, password string) (solkey.Key, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *Solana) Import(ctx context.Context, keyJSON []byte, password string) (solkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -205,17 +205,17 @@ func (_m *Solana) Import(keyJSON []byte, password string) (solkey.Key, error) { var r0 solkey.Key var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (solkey.Key, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (solkey.Key, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) solkey.Key); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) solkey.Key); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(solkey.Key) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/starknet.go b/core/services/keystore/mocks/starknet.go index c3d74a8389f..61fb89418b4 100644 --- a/core/services/keystore/mocks/starknet.go +++ b/core/services/keystore/mocks/starknet.go @@ -3,8 +3,11 @@ package mocks import ( - starkkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" + context "context" + mock "github.com/stretchr/testify/mock" + + starkkey "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" ) // StarkNet is an autogenerated mock type for the StarkNet type @@ -12,17 +15,17 @@ type StarkNet struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *StarkNet) Add(key starkkey.Key) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *StarkNet) Add(ctx context.Context, key starkkey.Key) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(starkkey.Key) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, starkkey.Key) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -30,9 +33,9 @@ func (_m *StarkNet) Add(key starkkey.Key) error { return r0 } -// Create provides a mock function with given fields: -func (_m *StarkNet) Create() (starkkey.Key, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *StarkNet) Create(ctx context.Context) (starkkey.Key, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -40,17 +43,17 @@ func (_m *StarkNet) Create() (starkkey.Key, error) { var r0 starkkey.Key var r1 error - if rf, ok := ret.Get(0).(func() (starkkey.Key, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (starkkey.Key, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() starkkey.Key); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) starkkey.Key); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(starkkey.Key) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -58,9 +61,9 @@ func (_m *StarkNet) Create() (starkkey.Key, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *StarkNet) Delete(id string) (starkkey.Key, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *StarkNet) Delete(ctx context.Context, id string) (starkkey.Key, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -68,17 +71,17 @@ func (_m *StarkNet) Delete(id string) (starkkey.Key, error) { var r0 starkkey.Key var r1 error - if rf, ok := ret.Get(0).(func(string) (starkkey.Key, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (starkkey.Key, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) starkkey.Key); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) starkkey.Key); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(starkkey.Key) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -86,17 +89,17 @@ func (_m *StarkNet) Delete(id string) (starkkey.Key, error) { return r0, r1 } -// EnsureKey provides a mock function with given fields: -func (_m *StarkNet) EnsureKey() error { - ret := _m.Called() +// EnsureKey provides a mock function with given fields: ctx +func (_m *StarkNet) EnsureKey(ctx context.Context) error { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for EnsureKey") } var r0 error - if rf, ok := ret.Get(0).(func() error); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) error); ok { + r0 = rf(ctx) } else { r0 = ret.Error(0) } @@ -192,9 +195,9 @@ func (_m *StarkNet) GetAll() ([]starkkey.Key, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *StarkNet) Import(keyJSON []byte, password string) (starkkey.Key, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *StarkNet) Import(ctx context.Context, keyJSON []byte, password string) (starkkey.Key, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -202,17 +205,17 @@ func (_m *StarkNet) Import(keyJSON []byte, password string) (starkkey.Key, error var r0 starkkey.Key var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (starkkey.Key, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (starkkey.Key, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) starkkey.Key); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) starkkey.Key); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(starkkey.Key) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/mocks/vrf.go b/core/services/keystore/mocks/vrf.go index ab730ebec67..acd6e02d434 100644 --- a/core/services/keystore/mocks/vrf.go +++ b/core/services/keystore/mocks/vrf.go @@ -3,6 +3,7 @@ package mocks import ( + context "context" big "math/big" mock "github.com/stretchr/testify/mock" @@ -15,17 +16,17 @@ type VRF struct { mock.Mock } -// Add provides a mock function with given fields: key -func (_m *VRF) Add(key vrfkey.KeyV2) error { - ret := _m.Called(key) +// Add provides a mock function with given fields: ctx, key +func (_m *VRF) Add(ctx context.Context, key vrfkey.KeyV2) error { + ret := _m.Called(ctx, key) if len(ret) == 0 { panic("no return value specified for Add") } var r0 error - if rf, ok := ret.Get(0).(func(vrfkey.KeyV2) error); ok { - r0 = rf(key) + if rf, ok := ret.Get(0).(func(context.Context, vrfkey.KeyV2) error); ok { + r0 = rf(ctx, key) } else { r0 = ret.Error(0) } @@ -33,9 +34,9 @@ func (_m *VRF) Add(key vrfkey.KeyV2) error { return r0 } -// Create provides a mock function with given fields: -func (_m *VRF) Create() (vrfkey.KeyV2, error) { - ret := _m.Called() +// Create provides a mock function with given fields: ctx +func (_m *VRF) Create(ctx context.Context) (vrfkey.KeyV2, error) { + ret := _m.Called(ctx) if len(ret) == 0 { panic("no return value specified for Create") @@ -43,17 +44,17 @@ func (_m *VRF) Create() (vrfkey.KeyV2, error) { var r0 vrfkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func() (vrfkey.KeyV2, error)); ok { - return rf() + if rf, ok := ret.Get(0).(func(context.Context) (vrfkey.KeyV2, error)); ok { + return rf(ctx) } - if rf, ok := ret.Get(0).(func() vrfkey.KeyV2); ok { - r0 = rf() + if rf, ok := ret.Get(0).(func(context.Context) vrfkey.KeyV2); ok { + r0 = rf(ctx) } else { r0 = ret.Get(0).(vrfkey.KeyV2) } - if rf, ok := ret.Get(1).(func() error); ok { - r1 = rf() + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) } else { r1 = ret.Error(1) } @@ -61,9 +62,9 @@ func (_m *VRF) Create() (vrfkey.KeyV2, error) { return r0, r1 } -// Delete provides a mock function with given fields: id -func (_m *VRF) Delete(id string) (vrfkey.KeyV2, error) { - ret := _m.Called(id) +// Delete provides a mock function with given fields: ctx, id +func (_m *VRF) Delete(ctx context.Context, id string) (vrfkey.KeyV2, error) { + ret := _m.Called(ctx, id) if len(ret) == 0 { panic("no return value specified for Delete") @@ -71,17 +72,17 @@ func (_m *VRF) Delete(id string) (vrfkey.KeyV2, error) { var r0 vrfkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func(string) (vrfkey.KeyV2, error)); ok { - return rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) (vrfkey.KeyV2, error)); ok { + return rf(ctx, id) } - if rf, ok := ret.Get(0).(func(string) vrfkey.KeyV2); ok { - r0 = rf(id) + if rf, ok := ret.Get(0).(func(context.Context, string) vrfkey.KeyV2); ok { + r0 = rf(ctx, id) } else { r0 = ret.Get(0).(vrfkey.KeyV2) } - if rf, ok := ret.Get(1).(func(string) error); ok { - r1 = rf(id) + if rf, ok := ret.Get(1).(func(context.Context, string) error); ok { + r1 = rf(ctx, id) } else { r1 = ret.Error(1) } @@ -205,9 +206,9 @@ func (_m *VRF) GetAll() ([]vrfkey.KeyV2, error) { return r0, r1 } -// Import provides a mock function with given fields: keyJSON, password -func (_m *VRF) Import(keyJSON []byte, password string) (vrfkey.KeyV2, error) { - ret := _m.Called(keyJSON, password) +// Import provides a mock function with given fields: ctx, keyJSON, password +func (_m *VRF) Import(ctx context.Context, keyJSON []byte, password string) (vrfkey.KeyV2, error) { + ret := _m.Called(ctx, keyJSON, password) if len(ret) == 0 { panic("no return value specified for Import") @@ -215,17 +216,17 @@ func (_m *VRF) Import(keyJSON []byte, password string) (vrfkey.KeyV2, error) { var r0 vrfkey.KeyV2 var r1 error - if rf, ok := ret.Get(0).(func([]byte, string) (vrfkey.KeyV2, error)); ok { - return rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) (vrfkey.KeyV2, error)); ok { + return rf(ctx, keyJSON, password) } - if rf, ok := ret.Get(0).(func([]byte, string) vrfkey.KeyV2); ok { - r0 = rf(keyJSON, password) + if rf, ok := ret.Get(0).(func(context.Context, []byte, string) vrfkey.KeyV2); ok { + r0 = rf(ctx, keyJSON, password) } else { r0 = ret.Get(0).(vrfkey.KeyV2) } - if rf, ok := ret.Get(1).(func([]byte, string) error); ok { - r1 = rf(keyJSON, password) + if rf, ok := ret.Get(1).(func(context.Context, []byte, string) error); ok { + r1 = rf(ctx, keyJSON, password) } else { r1 = ret.Error(1) } diff --git a/core/services/keystore/ocr.go b/core/services/keystore/ocr.go index dda5bfa13c3..7cacbbfff97 100644 --- a/core/services/keystore/ocr.go +++ b/core/services/keystore/ocr.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "github.com/pkg/errors" @@ -13,12 +14,12 @@ import ( type OCR interface { Get(id string) (ocrkey.KeyV2, error) GetAll() ([]ocrkey.KeyV2, error) - Create() (ocrkey.KeyV2, error) - Add(key ocrkey.KeyV2) error - Delete(id string) (ocrkey.KeyV2, error) - Import(keyJSON []byte, password string) (ocrkey.KeyV2, error) + Create(ctx context.Context) (ocrkey.KeyV2, error) + Add(ctx context.Context, key ocrkey.KeyV2) error + Delete(ctx context.Context, id string) (ocrkey.KeyV2, error) + Import(ctx context.Context, keyJSON []byte, password string) (ocrkey.KeyV2, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } // KeyNotFoundError is returned when we don't find a requested key @@ -64,7 +65,7 @@ func (ks *ocr) GetAll() (keys []ocrkey.KeyV2, _ error) { return keys, nil } -func (ks *ocr) Create() (ocrkey.KeyV2, error) { +func (ks *ocr) Create(ctx context.Context) (ocrkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -74,10 +75,10 @@ func (ks *ocr) Create() (ocrkey.KeyV2, error) { if err != nil { return ocrkey.KeyV2{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *ocr) Add(key ocrkey.KeyV2) error { +func (ks *ocr) Add(ctx context.Context, key ocrkey.KeyV2) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -86,10 +87,10 @@ func (ks *ocr) Add(key ocrkey.KeyV2) error { if _, found := ks.keyRing.OCR[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *ocr) Delete(id string) (ocrkey.KeyV2, error) { +func (ks *ocr) Delete(ctx context.Context, id string) (ocrkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -99,11 +100,11 @@ func (ks *ocr) Delete(id string) (ocrkey.KeyV2, error) { if err != nil { return ocrkey.KeyV2{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *ocr) Import(keyJSON []byte, password string) (ocrkey.KeyV2, error) { +func (ks *ocr) Import(ctx context.Context, keyJSON []byte, password string) (ocrkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -116,7 +117,7 @@ func (ks *ocr) Import(keyJSON []byte, password string) (ocrkey.KeyV2, error) { if _, found := ks.keyRing.OCR[key.ID()]; found { return ocrkey.KeyV2{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *ocr) Export(id string, password string) ([]byte, error) { @@ -133,7 +134,7 @@ func (ks *ocr) Export(id string, password string) ([]byte, error) { } // EnsureKey verifies whether the OCR key has been seeded, if not, it creates it. -func (ks *ocr) EnsureKey() error { +func (ks *ocr) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -151,7 +152,7 @@ func (ks *ocr) EnsureKey() error { ks.logger.Infof("Created OCR key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } func (ks *ocr) getByID(id string) (ocrkey.KeyV2, error) { diff --git a/core/services/keystore/ocr2.go b/core/services/keystore/ocr2.go index a6460bf1ae5..4edbe2ba741 100644 --- a/core/services/keystore/ocr2.go +++ b/core/services/keystore/ocr2.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "github.com/pkg/errors" @@ -15,12 +16,12 @@ type OCR2 interface { Get(id string) (ocr2key.KeyBundle, error) GetAll() ([]ocr2key.KeyBundle, error) GetAllOfType(chaintype.ChainType) ([]ocr2key.KeyBundle, error) - Create(chaintype.ChainType) (ocr2key.KeyBundle, error) - Add(key ocr2key.KeyBundle) error - Delete(id string) error - Import(keyJSON []byte, password string) (ocr2key.KeyBundle, error) + Create(context.Context, chaintype.ChainType) (ocr2key.KeyBundle, error) + Add(ctx context.Context, key ocr2key.KeyBundle) error + Delete(ctx context.Context, id string) error + Import(ctx context.Context, keyJSON []byte, password string) (ocr2key.KeyBundle, error) Export(id string, password string) ([]byte, error) - EnsureKeys(enabledChains ...chaintype.ChainType) error + EnsureKeys(ctx context.Context, enabledChains ...chaintype.ChainType) error } type ocr2 struct { @@ -67,16 +68,16 @@ func (ks ocr2) GetAllOfType(chainType chaintype.ChainType) ([]ocr2key.KeyBundle, return ks.getAllOfType(chainType) } -func (ks ocr2) Create(chainType chaintype.ChainType) (ocr2key.KeyBundle, error) { +func (ks ocr2) Create(ctx context.Context, chainType chaintype.ChainType) (ocr2key.KeyBundle, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { return nil, ErrLocked } - return ks.create(chainType) + return ks.create(ctx, chainType) } -func (ks ocr2) Add(key ocr2key.KeyBundle) error { +func (ks ocr2) Add(ctx context.Context, key ocr2key.KeyBundle) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -85,10 +86,10 @@ func (ks ocr2) Add(key ocr2key.KeyBundle) error { if _, found := ks.keyRing.OCR2[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks ocr2) Delete(id string) error { +func (ks ocr2) Delete(ctx context.Context, id string) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -98,11 +99,11 @@ func (ks ocr2) Delete(id string) error { if err != nil { return err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return err } -func (ks ocr2) Import(keyJSON []byte, password string) (ocr2key.KeyBundle, error) { +func (ks ocr2) Import(ctx context.Context, keyJSON []byte, password string) (ocr2key.KeyBundle, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -115,7 +116,7 @@ func (ks ocr2) Import(keyJSON []byte, password string) (ocr2key.KeyBundle, error if _, found := ks.keyRing.OCR[key.ID()]; found { return nil, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks ocr2) Export(id string, password string) ([]byte, error) { @@ -131,7 +132,7 @@ func (ks ocr2) Export(id string, password string) ([]byte, error) { return ocr2key.ToEncryptedJSON(key, password, ks.scryptParams) } -func (ks ocr2) EnsureKeys(enabledChains ...chaintype.ChainType) error { +func (ks ocr2) EnsureKeys(ctx context.Context, enabledChains ...chaintype.ChainType) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -148,7 +149,7 @@ func (ks ocr2) EnsureKeys(enabledChains ...chaintype.ChainType) error { continue } - created, err := ks.create(chainType) + created, err := ks.create(ctx, chainType) if err != nil { return err } @@ -177,7 +178,7 @@ func (ks ocr2) getAllOfType(chainType chaintype.ChainType) ([]ocr2key.KeyBundle, return keys, nil } -func (ks ocr2) create(chainType chaintype.ChainType) (ocr2key.KeyBundle, error) { +func (ks ocr2) create(ctx context.Context, chainType chaintype.ChainType) (ocr2key.KeyBundle, error) { if !chaintype.IsSupportedChainType(chainType) { return nil, chaintype.NewErrInvalidChainType(chainType) } @@ -185,5 +186,5 @@ func (ks ocr2) create(chainType chaintype.ChainType) (ocr2key.KeyBundle, error) if err != nil { return nil, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } diff --git a/core/services/keystore/ocr2_test.go b/core/services/keystore/ocr2_test.go index 9223538a766..f2c8715ab4f 100644 --- a/core/services/keystore/ocr2_test.go +++ b/core/services/keystore/ocr2_test.go @@ -1,13 +1,14 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" @@ -16,15 +17,15 @@ import ( func Test_OCR2KeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.OCR2() reset := func() { + ctx := context.Background() // Executed on cleanup _, err := db.Exec("DELETE FROM encrypted_key_rings") require.NoError(t, err) keyStore.ResetXXXTestOnly() - err = keyStore.Unlock(cltest.Password) + err = keyStore.Unlock(ctx, cltest.Password) require.NoError(t, err) } @@ -43,9 +44,10 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("creates a key with valid type", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) // lopp through different chain types for _, chain := range chaintype.SupportedChainTypes { - key, err := ks.Create(chain) + key, err := ks.Create(ctx, chain) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -55,6 +57,7 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("gets keys by type", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) created := map[chaintype.ChainType]bool{} for _, chain := range chaintype.SupportedChainTypes { @@ -64,7 +67,7 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { require.NoError(t, err) require.Len(t, keys, 0) - _, err = ks.Create(chain) + _, err = ks.Create(ctx, chain) require.NoError(t, err) created[chain] = true @@ -83,26 +86,28 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("errors when creating a key with an invalid type", func(t *testing.T) { defer reset() - _, err := ks.Create("foobar") + ctx := testutils.Context(t) + _, err := ks.Create(ctx, "foobar") require.Error(t, err) }) t.Run("imports and exports a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) for _, chain := range chaintype.SupportedChainTypes { - key, err := ks.Create(chain) + key, err := ks.Create(ctx, chain) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) _, err = ks.Export("non-existent", cltest.Password) assert.Error(t, err) - err = ks.Delete(key.ID()) + err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) - _, err = ks.Import([]byte(""), cltest.Password) + _, err = ks.Import(ctx, []byte(""), cltest.Password) assert.Error(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -114,19 +119,20 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) for _, chain := range chaintype.SupportedChainTypes { newKey, err := ocr2key.New(chain) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - err = ks.Delete(newKey.ID()) + err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) - err = ks.Delete(newKey.ID()) + err = ks.Delete(ctx, newKey.ID()) assert.Error(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -138,14 +144,15 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKeys(chaintype.SupportedChainTypes...) + ctx := testutils.Context(t) + err := ks.EnsureKeys(ctx, chaintype.SupportedChainTypes...) assert.NoError(t, err) keys, err := ks.GetAll() assert.NoError(t, err) require.Equal(t, len(chaintype.SupportedChainTypes), len(keys)) - err = ks.EnsureKeys(chaintype.SupportedChainTypes...) + err = ks.EnsureKeys(ctx, chaintype.SupportedChainTypes...) assert.NoError(t, err) // loop through different supported chain types @@ -158,7 +165,8 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { t.Run("ensures key only for enabled chains", func(t *testing.T) { defer reset() - err := ks.EnsureKeys(chaintype.EVM) + ctx := testutils.Context(t) + err := ks.EnsureKeys(ctx, chaintype.EVM) assert.NoError(t, err) keys, err := ks.GetAll() @@ -166,7 +174,7 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { require.Equal(t, 1, len(keys)) require.Equal(t, keys[0].ChainType(), chaintype.EVM) - err = ks.EnsureKeys(chaintype.Cosmos) + err = ks.EnsureKeys(ctx, chaintype.Cosmos) assert.NoError(t, err) keys, err = ks.GetAll() @@ -178,7 +186,7 @@ func Test_OCR2KeyStore_E2E(t *testing.T) { require.Equal(t, 1, len(cosmosKeys)) require.Equal(t, cosmosKeys[0].ChainType(), chaintype.Cosmos) - err = ks.EnsureKeys(chaintype.StarkNet) + err = ks.EnsureKeys(ctx, chaintype.StarkNet) assert.NoError(t, err) keys, err = ks.GetAll() diff --git a/core/services/keystore/ocr_test.go b/core/services/keystore/ocr_test.go index c65d576c452..b7a7b127f21 100644 --- a/core/services/keystore/ocr_test.go +++ b/core/services/keystore/ocr_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -8,7 +9,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" @@ -16,14 +17,14 @@ import ( func Test_OCRKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.OCR() reset := func() { + ctx := context.Background() // Executed on cleaup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -41,7 +42,8 @@ func Test_OCRKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -50,21 +52,22 @@ func Test_OCRKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) _, err = ks.Export("non-existent", cltest.Password) assert.Error(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) - _, err = ks.Import([]byte(""), cltest.Password) + _, err = ks.Import(ctx, []byte(""), cltest.Password) assert.Error(t, err) - _, err = ks.Import(exportJSON, cltest.Password) + _, err = ks.Import(ctx, exportJSON, cltest.Password) assert.Error(t, err) assert.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -74,18 +77,19 @@ func Test_OCRKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := ocrkey.NewV2() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) keys, err := ks.GetAll() require.NoError(t, err) assert.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) assert.Error(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -96,9 +100,10 @@ func Test_OCRKeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKey() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) require.NoError(t, err) - err = ks.EnsureKey() + err = ks.EnsureKey(ctx) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) @@ -106,8 +111,9 @@ func Test_OCRKeyStore_E2E(t *testing.T) { }) t.Run("imports a key exported from a v1 keystore", func(t *testing.T) { + ctx := testutils.Context(t) exportedKey := `{"id":"7cfd89bbb018e4778a44fd61172e8834dd24b4a2baf61ead795143b117221c61","onChainSigningAddress":"ocrsad_0x2ed5b18b62dacd7a85b6ed19247ea718bdae6114","offChainPublicKey":"ocroff_62a76d04e13dae5870071badea6b113a5123f4ac1a2cbae6b2fb7070dd9dbf2d","configPublicKey":"ocrcfg_75581baab36744671c2b1d75071b07b08b9cb631b3a7155d2f590744983d9c41","crypto":{"cipher":"aes-128-ctr","ciphertext":"60d2e679f08e0b1538cf609e25f2d32c0b7d408f24cab22dd05bffd3b5580c65552097e203f6546e2d792a4f6adb69449fee0fe4dd7f1060970907518e7c33331abd076388af842f03d05c193b03f22f6bf0423d4ae99dbb563c7158b4eac2a31b03c90fb9fd7be217804243151c36c33504469632bc2c89be33e7b9157edf172a52af4d49fa125b8d0358ea63ace90bc181a7164b548e0f12288ec08b919b46afad1b36dbaeda32d8d657a43908f802b6f2354473f538437ba3bd0b0d374d8e836e623484b655c95f4ef11e30baaa47b9075c6dbb53147c4b489f45a4bdcfa6b56ef2e6eaa9e9b88b570517c991de359d7f07226c00259810a8a4196b7d5331e4126529eac9bd80b47b5540940f89ad0e728b3dd50e6da316d9f3cf9b3be9b87ca6b7868daa7e4142fc4a65fc77deea6f4f2b4bce1e38337aa827160d8c50cad92d157309aa251180b894ab1ca9923d709d","cipherparams":{"iv":"a9507e6f2b073c1da1082d40a24864d1"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"267f9450f52af42a918ab5747043c88bd2035fa3d3e0f0cfd2b621981bc9320f"},"mac":"15aeb3fc1903f514bfe70cb2eb5a23820ba904f5edf8aeb1913d447797f74442"}}` - importedKey, err := ks.Import([]byte(exportedKey), "p4SsW0rD1!@#_") + importedKey, err := ks.Import(ctx, []byte(exportedKey), "p4SsW0rD1!@#_") require.NoError(t, err) require.Equal(t, "7cfd89bbb018e4778a44fd61172e8834dd24b4a2baf61ead795143b117221c61", importedKey.ID()) }) diff --git a/core/services/keystore/orm.go b/core/services/keystore/orm.go index 3d75d6f2369..d1c06f0b6a8 100644 --- a/core/services/keystore/orm.go +++ b/core/services/keystore/orm.go @@ -1,41 +1,41 @@ package keystore import ( + "context" "database/sql" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ethkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" - - "github.com/jmoiron/sqlx" - "github.com/pkg/errors" ) -func NewORM(db *sqlx.DB, lggr logger.Logger, cfg pg.QConfig) ksORM { +func NewORM(ds sqlutil.DataSource, lggr logger.Logger) ksORM { namedLogger := lggr.Named("KeystoreORM") return ksORM{ - q: pg.NewQ(db, namedLogger, cfg), + ds: ds, lggr: namedLogger, } } type ksORM struct { - q pg.Q + ds sqlutil.DataSource lggr logger.Logger } -func (orm ksORM) isEmpty() (bool, error) { +func (orm ksORM) isEmpty(ctx context.Context) (bool, error) { var count int64 - err := orm.q.QueryRow("SELECT count(*) FROM encrypted_key_rings").Scan(&count) + err := orm.ds.QueryRowxContext(ctx, "SELECT count(*) FROM encrypted_key_rings").Scan(&count) if err != nil { return false, err } return count == 0, nil } -func (orm ksORM) saveEncryptedKeyRing(kr *encryptedKeyRing, callbacks ...func(pg.Queryer) error) error { - return orm.q.Transaction(func(tx pg.Queryer) error { - _, err := tx.Exec(` +func (orm ksORM) saveEncryptedKeyRing(ctx context.Context, kr *encryptedKeyRing, callbacks ...func(sqlutil.DataSource) error) error { + return sqlutil.TransactDataSource(ctx, orm.ds, nil, func(tx sqlutil.DataSource) error { + _, err := tx.ExecContext(ctx, ` UPDATE encrypted_key_rings SET encrypted_keys = $1 `, kr.EncryptedKeys) @@ -52,11 +52,11 @@ func (orm ksORM) saveEncryptedKeyRing(kr *encryptedKeyRing, callbacks ...func(pg }) } -func (orm ksORM) getEncryptedKeyRing() (kr encryptedKeyRing, err error) { - err = orm.q.Get(&kr, `SELECT * FROM encrypted_key_rings LIMIT 1`) +func (orm ksORM) getEncryptedKeyRing(ctx context.Context) (kr encryptedKeyRing, err error) { + err = orm.ds.GetContext(ctx, &kr, `SELECT * FROM encrypted_key_rings LIMIT 1`) if errors.Is(err, sql.ErrNoRows) { sql := `INSERT INTO encrypted_key_rings (encrypted_keys, updated_at) VALUES (NULL, NOW()) RETURNING *;` - err2 := orm.q.Get(&kr, sql) + err2 := orm.ds.GetContext(ctx, &kr, sql) if err2 != nil { return kr, err2 @@ -67,10 +67,10 @@ func (orm ksORM) getEncryptedKeyRing() (kr encryptedKeyRing, err error) { return kr, nil } -func (orm ksORM) loadKeyStates() (*keyStates, error) { +func (orm ksORM) loadKeyStates(ctx context.Context) (*keyStates, error) { ks := newKeyStates() var ethkeystates []*ethkey.State - if err := orm.q.Select(ðkeystates, `SELECT id, address, evm_chain_id, disabled, created_at, updated_at FROM evm.key_states`); err != nil { + if err := orm.ds.SelectContext(ctx, ðkeystates, `SELECT id, address, evm_chain_id, disabled, created_at, updated_at FROM evm.key_states`); err != nil { return ks, errors.Wrap(err, "error loading evm.key_states from DB") } for _, state := range ethkeystates { diff --git a/core/services/keystore/p2p.go b/core/services/keystore/p2p.go index ee2c64c021d..ee5bc647b5d 100644 --- a/core/services/keystore/p2p.go +++ b/core/services/keystore/p2p.go @@ -1,13 +1,14 @@ package keystore import ( + "context" "fmt" "strings" "github.com/pkg/errors" + "github.com/smartcontractkit/chainlink-common/pkg/sqlutil" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" - "github.com/smartcontractkit/chainlink/v2/core/services/pg" ) //go:generate mockery --quiet --name P2P --output ./mocks/ --case=underscore --filename p2p.go @@ -15,12 +16,12 @@ import ( type P2P interface { Get(id p2pkey.PeerID) (p2pkey.KeyV2, error) GetAll() ([]p2pkey.KeyV2, error) - Create() (p2pkey.KeyV2, error) - Add(key p2pkey.KeyV2) error - Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) - Import(keyJSON []byte, password string) (p2pkey.KeyV2, error) + Create(ctx context.Context) (p2pkey.KeyV2, error) + Add(ctx context.Context, key p2pkey.KeyV2) error + Delete(ctx context.Context, id p2pkey.PeerID) (p2pkey.KeyV2, error) + Import(ctx context.Context, keyJSON []byte, password string) (p2pkey.KeyV2, error) Export(id p2pkey.PeerID, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error GetOrFirst(id p2pkey.PeerID) (p2pkey.KeyV2, error) } @@ -58,7 +59,7 @@ func (ks *p2p) GetAll() (keys []p2pkey.KeyV2, _ error) { return keys, nil } -func (ks *p2p) Create() (p2pkey.KeyV2, error) { +func (ks *p2p) Create(ctx context.Context) (p2pkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -68,10 +69,10 @@ func (ks *p2p) Create() (p2pkey.KeyV2, error) { if err != nil { return p2pkey.KeyV2{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *p2p) Add(key p2pkey.KeyV2) error { +func (ks *p2p) Add(ctx context.Context, key p2pkey.KeyV2) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -80,10 +81,10 @@ func (ks *p2p) Add(key p2pkey.KeyV2) error { if _, found := ks.keyRing.P2P[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *p2p) Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) { +func (ks *p2p) Delete(ctx context.Context, id p2pkey.PeerID) (p2pkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -93,14 +94,14 @@ func (ks *p2p) Delete(id p2pkey.PeerID) (p2pkey.KeyV2, error) { if err != nil { return p2pkey.KeyV2{}, err } - err = ks.safeRemoveKey(key, func(tx pg.Queryer) error { - _, err2 := tx.Exec(`DELETE FROM p2p_peers WHERE peer_id = $1`, key.ID()) + err = ks.safeRemoveKey(ctx, key, func(ds sqlutil.DataSource) error { + _, err2 := ds.ExecContext(ctx, `DELETE FROM p2p_peers WHERE peer_id = $1`, key.ID()) return err2 }) return key, err } -func (ks *p2p) Import(keyJSON []byte, password string) (p2pkey.KeyV2, error) { +func (ks *p2p) Import(ctx context.Context, keyJSON []byte, password string) (p2pkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -113,7 +114,7 @@ func (ks *p2p) Import(keyJSON []byte, password string) (p2pkey.KeyV2, error) { if _, found := ks.keyRing.P2P[key.ID()]; found { return p2pkey.KeyV2{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *p2p) Export(id p2pkey.PeerID, password string) ([]byte, error) { @@ -129,7 +130,7 @@ func (ks *p2p) Export(id p2pkey.PeerID, password string) ([]byte, error) { return key.ToEncryptedJSON(password, ks.scryptParams) } -func (ks *p2p) EnsureKey() error { +func (ks *p2p) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -147,7 +148,7 @@ func (ks *p2p) EnsureKey() error { ks.logger.Infof("Created P2P key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } var ( diff --git a/core/services/keystore/p2p_test.go b/core/services/keystore/p2p_test.go index 4dc44651473..f6c86a12814 100644 --- a/core/services/keystore/p2p_test.go +++ b/core/services/keystore/p2p_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "crypto/rand" "fmt" "testing" @@ -12,7 +13,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -20,15 +20,15 @@ import ( func Test_P2PKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.P2P() reset := func() { + ctx := context.Background() // Executed on cleanup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -49,7 +49,8 @@ func Test_P2PKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.PeerID()) require.NoError(t, err) @@ -58,7 +59,8 @@ func Test_P2PKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.PeerID(), cltest.Password) require.NoError(t, err) @@ -67,15 +69,15 @@ func Test_P2PKeyStore_E2E(t *testing.T) { require.NoError(t, err) _, err = ks.Export(nonExistent, cltest.Password) assert.Error(t, err) - _, err = ks.Delete(key.PeerID()) + _, err = ks.Delete(ctx, key.PeerID()) require.NoError(t, err) _, err = ks.Get(key.PeerID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) - _, err = ks.Import(exportJSON, cltest.Password) + _, err = ks.Import(ctx, exportJSON, cltest.Password) assert.Error(t, err) - _, err = ks.Import([]byte(""), cltest.Password) + _, err = ks.Import(ctx, []byte(""), cltest.Password) assert.Error(t, err) require.Equal(t, key.PeerID(), importedKey.PeerID()) retrievedKey, err := ks.Get(key.PeerID()) @@ -85,18 +87,19 @@ func Test_P2PKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := p2pkey.NewV2() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.PeerID()) + _, err = ks.Delete(ctx, newKey.PeerID()) require.NoError(t, err) - _, err = ks.Delete(newKey.PeerID()) + _, err = ks.Delete(ctx, newKey.PeerID()) assert.Error(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -107,14 +110,15 @@ func Test_P2PKeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKey() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) assert.NoError(t, err) keys, err := ks.GetAll() assert.NoError(t, err) require.Equal(t, 1, len(keys)) - err = ks.EnsureKey() + err = ks.EnsureKey(ctx) assert.NoError(t, err) keys, err = ks.GetAll() @@ -124,12 +128,13 @@ func Test_P2PKeyStore_E2E(t *testing.T) { t.Run("GetOrFirst", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) _, err := ks.GetOrFirst(p2pkey.PeerID{}) require.Contains(t, err.Error(), "no p2p keys exist") id := p2pkey.PeerID{0xa0} _, err = ks.GetOrFirst(id) require.Contains(t, err.Error(), fmt.Sprintf("unable to find P2P key with id %s", id)) - k1, err := ks.Create() + k1, err := ks.Create(ctx) require.NoError(t, err) k2, err := ks.GetOrFirst(p2pkey.PeerID{}) require.NoError(t, err) @@ -137,7 +142,7 @@ func Test_P2PKeyStore_E2E(t *testing.T) { k3, err := ks.GetOrFirst(k1.PeerID()) require.NoError(t, err) require.Equal(t, k1, k3) - _, err = ks.Create() + _, err = ks.Create(ctx) require.NoError(t, err) _, err = ks.GetOrFirst(p2pkey.PeerID{}) require.Contains(t, err.Error(), "multiple p2p keys found") @@ -152,7 +157,8 @@ func Test_P2PKeyStore_E2E(t *testing.T) { }) t.Run("clears p2p_peers on delete", func(t *testing.T) { - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) type P2PPeer struct { ID string @@ -181,14 +187,15 @@ func Test_P2PKeyStore_E2E(t *testing.T) { require.NoError(t, stmt.Get(&p2pPeer1, &p2pPeer1)) require.NoError(t, stmt.Get(&p2pPeer2, &p2pPeer2)) cltest.AssertCount(t, db, p2pTableName, 2) - _, err = ks.Delete(key.PeerID()) + _, err = ks.Delete(ctx, key.PeerID()) require.NoError(t, err) cltest.AssertCount(t, db, p2pTableName, 1) }) t.Run("imports a key exported from a v1 keystore", func(t *testing.T) { + ctx := testutils.Context(t) exportedKey := `{"publicKey":"fcc1fdebde28322dde17233fe7bd6dcde447d60d5cc1de518962deed102eea35","peerID":"p2p_12D3KooWSq2UZgSXvhGLG5uuAAmz1JNjxHMJViJB39aorvbbYo8p","crypto":{"cipher":"aes-128-ctr","ciphertext":"adb2dff72148a8cd467f6f06a03869e7cedf180cf2a4decdb86875b2e1cf3e58c4bd2b721ecdaa88a0825fa9abfc309bf32dbb35a5c0b6cb01ac89a956d78e0550eff351","cipherparams":{"iv":"6cc4381766a4efc39f762b2b8d09dfba"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"ff5055ae4cdcdc2d0404307d578262e2caeb0210f82db3a0ecbdba727c6f5259"},"mac":"d37e4f1dea98d85960ef3205099fc71741715ae56a3b1a8f9215a78de9b95595"}}` - importedKey, err := ks.Import([]byte(exportedKey), "p4SsW0rD1!@#_") + importedKey, err := ks.Import(ctx, []byte(exportedKey), "p4SsW0rD1!@#_") require.NoError(t, err) require.Equal(t, "12D3KooWSq2UZgSXvhGLG5uuAAmz1JNjxHMJViJB39aorvbbYo8p", importedKey.ID()) }) diff --git a/core/services/keystore/solana.go b/core/services/keystore/solana.go index 47b2cde7120..e95af37a7fa 100644 --- a/core/services/keystore/solana.go +++ b/core/services/keystore/solana.go @@ -14,12 +14,12 @@ import ( type Solana interface { Get(id string) (solkey.Key, error) GetAll() ([]solkey.Key, error) - Create() (solkey.Key, error) - Add(key solkey.Key) error - Delete(id string) (solkey.Key, error) - Import(keyJSON []byte, password string) (solkey.Key, error) + Create(ctx context.Context) (solkey.Key, error) + Add(ctx context.Context, key solkey.Key) error + Delete(ctx context.Context, id string) (solkey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (solkey.Key, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error Sign(ctx context.Context, id string, msg []byte) (signature []byte, err error) } @@ -72,7 +72,7 @@ func (ks *solana) GetAll() (keys []solkey.Key, _ error) { return keys, nil } -func (ks *solana) Create() (solkey.Key, error) { +func (ks *solana) Create(ctx context.Context) (solkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -82,10 +82,10 @@ func (ks *solana) Create() (solkey.Key, error) { if err != nil { return solkey.Key{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *solana) Add(key solkey.Key) error { +func (ks *solana) Add(ctx context.Context, key solkey.Key) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -94,10 +94,10 @@ func (ks *solana) Add(key solkey.Key) error { if _, found := ks.keyRing.Solana[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *solana) Delete(id string) (solkey.Key, error) { +func (ks *solana) Delete(ctx context.Context, id string) (solkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -107,11 +107,11 @@ func (ks *solana) Delete(id string) (solkey.Key, error) { if err != nil { return solkey.Key{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *solana) Import(keyJSON []byte, password string) (solkey.Key, error) { +func (ks *solana) Import(ctx context.Context, keyJSON []byte, password string) (solkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -124,7 +124,7 @@ func (ks *solana) Import(keyJSON []byte, password string) (solkey.Key, error) { if _, found := ks.keyRing.Solana[key.ID()]; found { return solkey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *solana) Export(id string, password string) ([]byte, error) { @@ -140,7 +140,7 @@ func (ks *solana) Export(id string, password string) ([]byte, error) { return key.ToEncryptedJSON(password, ks.scryptParams) } -func (ks *solana) EnsureKey() error { +func (ks *solana) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -157,7 +157,7 @@ func (ks *solana) EnsureKey() error { ks.logger.Infof("Created Solana key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } func (ks *solana) Sign(_ context.Context, id string, msg []byte) (signature []byte, err error) { diff --git a/core/services/keystore/solana_test.go b/core/services/keystore/solana_test.go index cf2515f5f70..7355404d093 100644 --- a/core/services/keystore/solana_test.go +++ b/core/services/keystore/solana_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "testing" "github.com/stretchr/testify/assert" @@ -9,7 +10,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/solkey" @@ -17,15 +17,15 @@ import ( func Test_SolanaKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.Solana() reset := func() { + ctx := context.Background() // Executed on cleanup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -43,7 +43,8 @@ func Test_SolanaKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -52,21 +53,22 @@ func Test_SolanaKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) _, err = ks.Export("non-existent", cltest.Password) assert.Error(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) - _, err = ks.Import(exportJSON, cltest.Password) + _, err = ks.Import(ctx, exportJSON, cltest.Password) assert.Error(t, err) - _, err = ks.Import([]byte(""), cltest.Password) + _, err = ks.Import(ctx, []byte(""), cltest.Password) assert.Error(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -76,18 +78,19 @@ func Test_SolanaKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := solkey.New() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) assert.Error(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) assert.Error(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -98,10 +101,11 @@ func Test_SolanaKeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKey() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) assert.NoError(t, err) - err = ks.EnsureKey() + err = ks.EnsureKey(ctx) assert.NoError(t, err) keys, err := ks.GetAll() @@ -111,9 +115,10 @@ func Test_SolanaKeyStore_E2E(t *testing.T) { t.Run("sign tx", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := solkey.New() require.NoError(t, err) - require.NoError(t, ks.Add(newKey)) + require.NoError(t, ks.Add(ctx, newKey)) // sign unknown ID _, err = ks.Sign(testutils.Context(t), "not-real", nil) diff --git a/core/services/keystore/starknet.go b/core/services/keystore/starknet.go index 6b6afa987c6..e6655a4d3f2 100644 --- a/core/services/keystore/starknet.go +++ b/core/services/keystore/starknet.go @@ -18,12 +18,12 @@ import ( type StarkNet interface { Get(id string) (starkkey.Key, error) GetAll() ([]starkkey.Key, error) - Create() (starkkey.Key, error) - Add(key starkkey.Key) error - Delete(id string) (starkkey.Key, error) - Import(keyJSON []byte, password string) (starkkey.Key, error) + Create(ctx context.Context) (starkkey.Key, error) + Add(ctx context.Context, key starkkey.Key) error + Delete(ctx context.Context, id string) (starkkey.Key, error) + Import(ctx context.Context, keyJSON []byte, password string) (starkkey.Key, error) Export(id string, password string) ([]byte, error) - EnsureKey() error + EnsureKey(ctx context.Context) error } type starknet struct { @@ -59,7 +59,7 @@ func (ks *starknet) GetAll() (keys []starkkey.Key, _ error) { return keys, nil } -func (ks *starknet) Create() (starkkey.Key, error) { +func (ks *starknet) Create(ctx context.Context) (starkkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -69,10 +69,10 @@ func (ks *starknet) Create() (starkkey.Key, error) { if err != nil { return starkkey.Key{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *starknet) Add(key starkkey.Key) error { +func (ks *starknet) Add(ctx context.Context, key starkkey.Key) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -81,10 +81,10 @@ func (ks *starknet) Add(key starkkey.Key) error { if _, found := ks.keyRing.StarkNet[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *starknet) Delete(id string) (starkkey.Key, error) { +func (ks *starknet) Delete(ctx context.Context, id string) (starkkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -94,11 +94,11 @@ func (ks *starknet) Delete(id string) (starkkey.Key, error) { if err != nil { return starkkey.Key{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *starknet) Import(keyJSON []byte, password string) (starkkey.Key, error) { +func (ks *starknet) Import(ctx context.Context, keyJSON []byte, password string) (starkkey.Key, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -111,7 +111,7 @@ func (ks *starknet) Import(keyJSON []byte, password string) (starkkey.Key, error if _, found := ks.keyRing.StarkNet[key.ID()]; found { return starkkey.Key{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *starknet) Export(id string, password string) ([]byte, error) { @@ -127,7 +127,7 @@ func (ks *starknet) Export(id string, password string) ([]byte, error) { return starkkey.ToEncryptedJSON(key, password, ks.scryptParams) } -func (ks *starknet) EnsureKey() error { +func (ks *starknet) EnsureKey(ctx context.Context) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -144,7 +144,7 @@ func (ks *starknet) EnsureKey() error { ks.logger.Infof("Created StarkNet key with ID %s", key.ID()) - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } func (ks *starknet) getByID(id string) (starkkey.Key, error) { diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go index 43624a4159e..97d4219272b 100644 --- a/core/services/keystore/starknet_test.go +++ b/core/services/keystore/starknet_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "fmt" "math/big" "testing" @@ -14,7 +15,6 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/starkkey" @@ -25,15 +25,15 @@ import ( func Test_StarkNetKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.StarkNet() reset := func() { + ctx := context.Background() // Executed on cleanup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -51,7 +51,8 @@ func Test_StarkNetKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -60,15 +61,16 @@ func Test_StarkNetKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -78,14 +80,15 @@ func Test_StarkNetKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := starkkey.New() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -96,10 +99,11 @@ func Test_StarkNetKeyStore_E2E(t *testing.T) { t.Run("ensures key", func(t *testing.T) { defer reset() - err := ks.EnsureKey() + ctx := testutils.Context(t) + err := ks.EnsureKey(ctx) assert.NoError(t, err) - err = ks.EnsureKey() + err = ks.EnsureKey(ctx) assert.NoError(t, err) keys, err := ks.GetAll() diff --git a/core/services/keystore/vrf.go b/core/services/keystore/vrf.go index 91e77557674..7b222e193d1 100644 --- a/core/services/keystore/vrf.go +++ b/core/services/keystore/vrf.go @@ -1,6 +1,7 @@ package keystore import ( + "context" "fmt" "math/big" @@ -14,10 +15,10 @@ import ( type VRF interface { Get(id string) (vrfkey.KeyV2, error) GetAll() ([]vrfkey.KeyV2, error) - Create() (vrfkey.KeyV2, error) - Add(key vrfkey.KeyV2) error - Delete(id string) (vrfkey.KeyV2, error) - Import(keyJSON []byte, password string) (vrfkey.KeyV2, error) + Create(ctx context.Context) (vrfkey.KeyV2, error) + Add(ctx context.Context, key vrfkey.KeyV2) error + Delete(ctx context.Context, id string) (vrfkey.KeyV2, error) + Import(ctx context.Context, keyJSON []byte, password string) (vrfkey.KeyV2, error) Export(id string, password string) ([]byte, error) GenerateProof(id string, seed *big.Int) (vrfkey.Proof, error) @@ -60,7 +61,7 @@ func (ks *vrf) GetAll() (keys []vrfkey.KeyV2, _ error) { return keys, nil } -func (ks *vrf) Create() (vrfkey.KeyV2, error) { +func (ks *vrf) Create(ctx context.Context) (vrfkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -70,10 +71,10 @@ func (ks *vrf) Create() (vrfkey.KeyV2, error) { if err != nil { return vrfkey.KeyV2{}, err } - return key, ks.safeAddKey(key) + return key, ks.safeAddKey(ctx, key) } -func (ks *vrf) Add(key vrfkey.KeyV2) error { +func (ks *vrf) Add(ctx context.Context, key vrfkey.KeyV2) error { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -82,10 +83,10 @@ func (ks *vrf) Add(key vrfkey.KeyV2) error { if _, found := ks.keyRing.VRF[key.ID()]; found { return fmt.Errorf("key with ID %s already exists", key.ID()) } - return ks.safeAddKey(key) + return ks.safeAddKey(ctx, key) } -func (ks *vrf) Delete(id string) (vrfkey.KeyV2, error) { +func (ks *vrf) Delete(ctx context.Context, id string) (vrfkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -95,11 +96,11 @@ func (ks *vrf) Delete(id string) (vrfkey.KeyV2, error) { if err != nil { return vrfkey.KeyV2{}, err } - err = ks.safeRemoveKey(key) + err = ks.safeRemoveKey(ctx, key) return key, err } -func (ks *vrf) Import(keyJSON []byte, password string) (vrfkey.KeyV2, error) { +func (ks *vrf) Import(ctx context.Context, keyJSON []byte, password string) (vrfkey.KeyV2, error) { ks.lock.Lock() defer ks.lock.Unlock() if ks.isLocked() { @@ -112,7 +113,7 @@ func (ks *vrf) Import(keyJSON []byte, password string) (vrfkey.KeyV2, error) { if _, found := ks.keyRing.VRF[key.ID()]; found { return vrfkey.KeyV2{}, fmt.Errorf("key with ID %s already exists", key.ID()) } - return key, ks.keyManager.safeAddKey(key) + return key, ks.keyManager.safeAddKey(ctx, key) } func (ks *vrf) Export(id string, password string) ([]byte, error) { diff --git a/core/services/keystore/vrf_test.go b/core/services/keystore/vrf_test.go index 77fccd865ff..4b77377d5e8 100644 --- a/core/services/keystore/vrf_test.go +++ b/core/services/keystore/vrf_test.go @@ -1,6 +1,7 @@ package keystore_test import ( + "context" "fmt" "math/big" "testing" @@ -9,7 +10,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" @@ -19,14 +20,14 @@ import ( func Test_VRFKeyStore_E2E(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - keyStore := keystore.ExposedNewMaster(t, db, cfg.Database()) - require.NoError(t, keyStore.Unlock(cltest.Password)) + keyStore := keystore.ExposedNewMaster(t, db) + require.NoError(t, keyStore.Unlock(testutils.Context(t), cltest.Password)) ks := keyStore.VRF() reset := func() { + ctx := context.Background() // Executed during cleanup require.NoError(t, utils.JustError(db.Exec("DELETE FROM encrypted_key_rings"))) keyStore.ResetXXXTestOnly() - require.NoError(t, keyStore.Unlock(cltest.Password)) + require.NoError(t, keyStore.Unlock(ctx, cltest.Password)) } t.Run("initializes with an empty state", func(t *testing.T) { @@ -44,7 +45,8 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("creates a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) retrievedKey, err := ks.Get(key.ID()) require.NoError(t, err) @@ -53,15 +55,16 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("imports and exports a key", func(t *testing.T) { defer reset() - key, err := ks.Create() + ctx := testutils.Context(t) + key, err := ks.Create(ctx) require.NoError(t, err) exportJSON, err := ks.Export(key.ID(), cltest.Password) require.NoError(t, err) - _, err = ks.Delete(key.ID()) + _, err = ks.Delete(ctx, key.ID()) require.NoError(t, err) _, err = ks.Get(key.ID()) require.Error(t, err) - importedKey, err := ks.Import(exportJSON, cltest.Password) + importedKey, err := ks.Import(ctx, exportJSON, cltest.Password) require.NoError(t, err) require.Equal(t, key.ID(), importedKey.ID()) retrievedKey, err := ks.Get(key.ID()) @@ -71,14 +74,15 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("adds an externally created key / deletes a key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) newKey, err := vrfkey.NewV2() require.NoError(t, err) - err = ks.Add(newKey) + err = ks.Add(ctx, newKey) require.NoError(t, err) keys, err := ks.GetAll() require.NoError(t, err) require.Equal(t, 1, len(keys)) - _, err = ks.Delete(newKey.ID()) + _, err = ks.Delete(ctx, newKey.ID()) require.NoError(t, err) keys, err = ks.GetAll() require.NoError(t, err) @@ -89,13 +93,14 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("fails to add an already added key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) k, err := vrfkey.NewV2() require.NoError(t, err) - err = ks.Add(k) + err = ks.Add(ctx, k) require.NoError(t, err) - err = ks.Add(k) + err = ks.Add(ctx, k) assert.Error(t, err) assert.Equal(t, fmt.Sprintf("key with ID %s already exists", k.ID()), err.Error()) @@ -103,14 +108,15 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("fails to delete a key that doesn't exists", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) k, err := vrfkey.NewV2() require.NoError(t, err) - err = ks.Add(k) + err = ks.Add(ctx, k) require.NoError(t, err) - fk, err := ks.Delete("non-existent") + fk, err := ks.Delete(ctx, "non-existent") assert.Zero(t, fk) assert.Error(t, err) @@ -118,22 +124,24 @@ func Test_VRFKeyStore_E2E(t *testing.T) { t.Run("imports a key exported from a v1 keystore", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) exportedKey := `{"PublicKey":"0xd2377bc6be8a2c5ce163e1867ee42ef111e320686f940a98e52e9c019ca0606800","vrf_key":{"address":"b94276ad4e5452732ec0cccf30ef7919b67844b6","crypto":{"cipher":"aes-128-ctr","ciphertext":"ff66d61d02dba54a61bab1ceb8414643f9e76b7351785d2959e2c8b50ee69a92","cipherparams":{"iv":"75705da271b11e330a27b8d593a3930c"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"efe5b372e4fe79d0af576a79d65a1ee35d0792d9c92b70107b5ada1817ea7c7b"},"mac":"e4d0bb08ffd004ab03aeaa42367acbd9bb814c6cfd981f5157503f54c30816e7"},"version":3}}` - importedKey, err := ks.Import([]byte(exportedKey), "p4SsW0rD1!@#_") + importedKey, err := ks.Import(ctx, []byte(exportedKey), "p4SsW0rD1!@#_") require.NoError(t, err) require.Equal(t, "0xd2377bc6be8a2c5ce163e1867ee42ef111e320686f940a98e52e9c019ca0606800", importedKey.ID()) }) t.Run("fails to import an already imported key", func(t *testing.T) { defer reset() + ctx := testutils.Context(t) exportedKey := `{"PublicKey":"0xd2377bc6be8a2c5ce163e1867ee42ef111e320686f940a98e52e9c019ca0606800","vrf_key":{"address":"b94276ad4e5452732ec0cccf30ef7919b67844b6","crypto":{"cipher":"aes-128-ctr","ciphertext":"ff66d61d02dba54a61bab1ceb8414643f9e76b7351785d2959e2c8b50ee69a92","cipherparams":{"iv":"75705da271b11e330a27b8d593a3930c"},"kdf":"scrypt","kdfparams":{"dklen":32,"n":262144,"p":1,"r":8,"salt":"efe5b372e4fe79d0af576a79d65a1ee35d0792d9c92b70107b5ada1817ea7c7b"},"mac":"e4d0bb08ffd004ab03aeaa42367acbd9bb814c6cfd981f5157503f54c30816e7"},"version":3}}` - importedKey, err := ks.Import([]byte(exportedKey), "p4SsW0rD1!@#_") + importedKey, err := ks.Import(ctx, []byte(exportedKey), "p4SsW0rD1!@#_") require.NoError(t, err) keyStore.SetPassword("p4SsW0rD1!@#_") - k, err := ks.Import([]byte(exportedKey), "p4SsW0rD1!@#_") + k, err := ks.Import(ctx, []byte(exportedKey), "p4SsW0rD1!@#_") assert.Zero(t, k) assert.Error(t, err) @@ -158,9 +166,10 @@ func Test_VRFKeyStore_E2E(t *testing.T) { }) t.Run("generates a proof for a key", func(t *testing.T) { + ctx := testutils.Context(t) k, err := vrfkey.NewV2() require.NoError(t, err) - err = ks.Add(k) + err = ks.Add(ctx, k) require.NoError(t, err) pf, err := ks.GenerateProof(k.ID(), big.NewInt(int64(1))) diff --git a/core/services/ocr/database_test.go b/core/services/ocr/database_test.go index 8b8d64c49c9..a2559ca2a87 100644 --- a/core/services/ocr/database_test.go +++ b/core/services/ocr/database_test.go @@ -16,7 +16,6 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/chains/evm/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/ocr" ) @@ -25,8 +24,7 @@ func Test_DB_ReadWriteState(t *testing.T) { db := pgtest.NewSqlxDB(t) configDigest := cltest.MakeConfigDigest(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := cltest.MustInsertOffchainreportingOracleSpec(t, db, key.EIP55Address) @@ -106,7 +104,6 @@ func Test_DB_ReadWriteState(t *testing.T) { func Test_DB_ReadWriteConfig(t *testing.T) { db := pgtest.NewSqlxDB(t) sqlDB := db - cfg := configtest.NewTestGeneralConfig(t) config := ocrtypes.ContractConfig{ ConfigDigest: cltest.MakeConfigDigest(t), @@ -116,7 +113,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { EncodedConfigVersion: uint64(987654), Encoded: []byte{1, 2, 3, 4, 5}, } - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := cltest.MustInsertOffchainreportingOracleSpec(t, db, key.EIP55Address) transmitterAddress := key.Address @@ -188,8 +185,7 @@ func assertPendingTransmissionEqual(t *testing.T, pt1, pt2 ocrtypes.PendingTrans func Test_DB_PendingTransmissions(t *testing.T) { db := pgtest.NewSqlxDB(t) sqlDB := db - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := cltest.MustInsertOffchainreportingOracleSpec(t, db, key.EIP55Address) diff --git a/core/services/ocr2/database_test.go b/core/services/ocr2/database_test.go index 486bf1fd708..6e4f8f5dd66 100644 --- a/core/services/ocr2/database_test.go +++ b/core/services/ocr2/database_test.go @@ -61,7 +61,7 @@ func Test_DB_ReadWriteState(t *testing.T) { configDigest := testhelpers.MakeConfigDigest(t) cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, sqlDB, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) @@ -152,7 +152,7 @@ func Test_DB_ReadWriteConfig(t *testing.T) { OffchainConfig: []byte{0x03, 0x04}, } cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, sqlDB, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) spec := MustInsertOCROracleSpec(t, sqlDB, key.EIP55Address) lggr := logger.TestLogger(t) @@ -239,7 +239,7 @@ func Test_DB_PendingTransmissions(t *testing.T) { sqlDB := setupDB(t) cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, sqlDB, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, sqlDB).Eth() key, _ := cltest.MustInsertRandomKey(t, ethKeyStore) lggr := logger.TestLogger(t) diff --git a/core/services/ocr2/delegate_test.go b/core/services/ocr2/delegate_test.go index ea8693d48ce..bae1f5f3e78 100644 --- a/core/services/ocr2/delegate_test.go +++ b/core/services/ocr2/delegate_test.go @@ -27,6 +27,7 @@ import ( ) func TestGetEVMEffectiveTransmitterID(t *testing.T) { + ctx := testutils.Context(t) customChainID := big.New(testutils.NewRandomEVMChainID()) config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -39,8 +40,8 @@ func TestGetEVMEffectiveTransmitterID(t *testing.T) { }) }) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) - require.NoError(t, keyStore.OCR2().Add(cltest.DefaultOCR2Key)) + keyStore := cltest.NewKeyStore(t, db) + require.NoError(t, keyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) lggr := logger.TestLogger(t) txManager := txmmocks.NewMockEvmTxManager(t) diff --git a/core/services/ocr2/plugins/dkg/config/config_test.go b/core/services/ocr2/plugins/dkg/config/config_test.go index fe796a9ad6c..f8cc1265ee1 100644 --- a/core/services/ocr2/plugins/dkg/config/config_test.go +++ b/core/services/ocr2/plugins/dkg/config/config_test.go @@ -7,21 +7,21 @@ import ( "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/dkg/config" ) func TestValidatePluginConfig(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) - cfg := configtest.NewGeneralConfig(t, nil) db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) + kst := cltest.NewKeyStore(t, db) - dkgEncryptKey, err := kst.DKGEncrypt().Create() + dkgEncryptKey, err := kst.DKGEncrypt().Create(ctx) require.NoError(t, err) - dkgSignKey, err := kst.DKGSign().Create() + dkgSignKey, err := kst.DKGSign().Create(ctx) require.NoError(t, err) encryptKeyBytes, err := dkgEncryptKey.PublicKey.MarshalBinary() diff --git a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go index ae9bf5f01cd..3f96b49cfe0 100644 --- a/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go +++ b/core/services/ocr2/plugins/functions/integration_tests/v1/internal/testutils.go @@ -317,6 +317,7 @@ func StartNewNode( ocr2Keystore []byte, thresholdKeyShare string, ) *Node { + ctx := testutils.Context(t) p2pKey := keystest.NewP2PKeyV2(t) config, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Insecure.OCRDevelopmentMode = ptr(true) @@ -371,9 +372,9 @@ func StartNewNode( var kb ocr2key.KeyBundle if ocr2Keystore != nil { - kb, err = app.GetKeyStore().OCR2().Import(ocr2Keystore, "testPassword") + kb, err = app.GetKeyStore().OCR2().Import(ctx, ocr2Keystore, "testPassword") } else { - kb, err = app.GetKeyStore().OCR2().Create("evm") + kb, err = app.GetKeyStore().OCR2().Create(ctx, "evm") } require.NoError(t, err) diff --git a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go index 02136583e49..ae74cb218ee 100644 --- a/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go +++ b/core/services/ocr2/plugins/generic/pipeline_runner_adapter_test.go @@ -37,13 +37,14 @@ answer; func TestAdapter_Integration(t *testing.T) { testutils.SkipShortDB(t) + ctx := testutils.Context(t) logger := logger.TestLogger(t) cfg := configtest.NewTestGeneralConfig(t) url := cfg.Database().URL() db, err := pg.NewConnection(url.String(), cfg.Database().Dialect(), cfg.Database()) require.NoError(t, err) - keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger, cfg.Database()) + keystore := keystore.NewInMemory(db, utils.FastScryptParams, logger) pipelineORM := pipeline.NewORM(db, logger, cfg.JobPipeline().MaxSuccessfulRuns()) bridgesORM := bridges.NewORM(db) jobORM := job.NewORM(db, pipelineORM, bridgesORM, keystore, logger, cfg.Database()) @@ -59,7 +60,7 @@ func TestAdapter_Integration(t *testing.T) { http.DefaultClient, http.DefaultClient, ) - err = keystore.Unlock(cfg.Password().Keystore()) + err = keystore.Unlock(ctx, cfg.Password().Keystore()) require.NoError(t, err) jb, err := ocr2validate.ValidatedOracleSpecToml(testutils.Context(t), cfg.OCR2(), cfg.Insecure(), testspecs.GetOCR2EVMSpecMinimal(), nil) require.NoError(t, err) diff --git a/core/services/ocr2/plugins/ocr2keeper/integration_test.go b/core/services/ocr2/plugins/ocr2keeper/integration_test.go index ea752256232..1054c59dd1c 100644 --- a/core/services/ocr2/plugins/ocr2keeper/integration_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/integration_test.go @@ -112,6 +112,7 @@ func setupNode( p2pV2Bootstrappers []commontypes.BootstrapperLocator, mercury mercury.MercuryEndpointMock, ) (chainlink.Application, string, common.Address, ocr2key.KeyBundle) { + ctx := testutils.Context(t) p2pKey := keystest.NewP2PKeyV2(t) p2paddresses := []string{fmt.Sprintf("127.0.0.1:%d", port)} cfg, _ := heavyweight.FullTestDBV2(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -143,10 +144,10 @@ func setupNode( }) app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, backend, nodeKey, p2pKey) - kb, err := app.GetKeyStore().OCR2().Create(chaintype.EVM) + kb, err := app.GetKeyStore().OCR2().Create(ctx, chaintype.EVM) require.NoError(t, err) - err = app.Start(testutils.Context(t)) + err = app.Start(ctx) require.NoError(t, err) t.Cleanup(func() { diff --git a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go index 94c4c0bb8fc..ac2695dc632 100644 --- a/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go +++ b/core/services/ocr2/plugins/ocr2vrf/internal/ocr2vrf_integration_test.go @@ -312,7 +312,7 @@ func setupNodeOCR2( b.Commit() } - kb, err := app.GetKeyStore().OCR2().Create("evm") + kb, err := app.GetKeyStore().OCR2().Create(ctx, "evm") require.NoError(t, err) return &ocr2Node{ @@ -371,10 +371,10 @@ func runOCR2VRFTest(t *testing.T, useForwarders bool) { node := setupNodeOCR2(t, uni.owner, ports[i], fmt.Sprintf("ocr2vrforacle%d", i), uni.backend, useForwarders, bootstrappers) sendingKeys = append(sendingKeys, node.sendingKeys) - dkgSignKey, err := node.app.GetKeyStore().DKGSign().Create() + dkgSignKey, err := node.app.GetKeyStore().DKGSign().Create(ctx) require.NoError(t, err) - dkgEncryptKey, err := node.app.GetKeyStore().DKGEncrypt().Create() + dkgEncryptKey, err := node.app.GetKeyStore().DKGEncrypt().Create(ctx) require.NoError(t, err) kbs = append(kbs, node.keybundle) diff --git a/core/services/ocrcommon/peer_wrapper_test.go b/core/services/ocrcommon/peer_wrapper_test.go index f46b2af27c5..e87f211fd21 100644 --- a/core/services/ocrcommon/peer_wrapper_test.go +++ b/core/services/ocrcommon/peer_wrapper_test.go @@ -33,20 +33,18 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) require.Contains(t, pw.Start(testutils.Context(t)).Error(), "No P2P keys found in keystore. Peer wrapper will not be fully initialized") }) t.Run("with one p2p key and matching P2P.PeerID returns nil", func(t *testing.T) { - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.P2P.V2.Enabled = ptr(true) - }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - k, err := keyStore.P2P().Create() + ctx := testutils.Context(t) + keyStore := cltest.NewKeyStore(t, db) + k, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - cfg = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} c.P2P.PeerID = ptr(k.PeerID()) @@ -58,13 +56,14 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { }) t.Run("with one p2p key and mismatching P2P.PeerID returns error", func(t *testing.T) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.PeerID = ptr(p2pkey.PeerID(peerID)) }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) - _, err := keyStore.P2P().Create() + _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) @@ -73,15 +72,12 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { }) t.Run("with multiple p2p keys and valid P2P.PeerID returns nil", func(t *testing.T) { - cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { - c.P2P.V2.Enabled = ptr(true) - c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} - }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - k2, err := keyStore.P2P().Create() + ctx := testutils.Context(t) + keyStore := cltest.NewKeyStore(t, db) + k2, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - cfg = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} c.P2P.PeerID = ptr(k2.PeerID()) @@ -94,14 +90,15 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { }) t.Run("with multiple p2p keys and mismatching P2P.PeerID returns error", func(t *testing.T) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.V2.ListenAddresses = &[]string{fmt.Sprintf("127.0.0.1:%d", freeport.GetOne(t))} c.P2P.PeerID = ptr(p2pkey.PeerID(peerID)) }) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) - _, err := keyStore.P2P().Create() + _, err := keyStore.P2P().Create(ctx) require.NoError(t, err) pw := ocrcommon.NewSingletonPeerWrapper(keyStore, cfg.P2P(), cfg.OCR(), cfg.Database(), db, logger.TestLogger(t)) @@ -112,15 +109,15 @@ func Test_SingletonPeerWrapper_Start(t *testing.T) { func Test_SingletonPeerWrapper_Close(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) - k, err := keyStore.P2P().Create() + keyStore := cltest.NewKeyStore(t, db) + k, err := keyStore.P2P().Create(ctx) require.NoError(t, err) - cfg = configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { + cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.P2P.V2.Enabled = ptr(true) c.P2P.PeerID = ptr(k.PeerID()) c.P2P.V2.DeltaDial = commonconfig.MustNewDuration(100 * time.Millisecond) diff --git a/core/services/ocrcommon/transmitter_test.go b/core/services/ocrcommon/transmitter_test.go index c56896ab2b9..d6a07190800 100644 --- a/core/services/ocrcommon/transmitter_test.go +++ b/core/services/ocrcommon/transmitter_test.go @@ -13,7 +13,6 @@ import ( txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon" ) @@ -26,8 +25,7 @@ func Test_DefaultTransmitter_CreateEthTransaction(t *testing.T) { t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -67,8 +65,7 @@ func Test_DefaultTransmitter_Forwarding_Enabled_CreateEthTransaction(t *testing. t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, fromAddress2 := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -119,8 +116,7 @@ func Test_DefaultTransmitter_Forwarding_Enabled_CreateEthTransaction_Round_Robin t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() fromAddress := common.Address{} @@ -150,8 +146,7 @@ func Test_DefaultTransmitter_Forwarding_Enabled_CreateEthTransaction_No_Keystore t.Parallel() db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) _, fromAddress2 := cltest.MustInsertRandomKey(t, ethKeyStore) diff --git a/core/services/pipeline/orm_test.go b/core/services/pipeline/orm_test.go index 88155bc04ba..bba928534ba 100644 --- a/core/services/pipeline/orm_test.go +++ b/core/services/pipeline/orm_test.go @@ -74,7 +74,7 @@ func setupORM(t *testing.T, heavy bool) (db *sqlx.DB, orm pipeline.ORM, jorm job orm = pipeline.NewORM(db, logger.TestLogger(t), cfg.JobPipelineMaxSuccessfulRuns()) config := configtest.NewTestGeneralConfig(t) lggr := logger.TestLogger(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) bridgeORM := bridges.NewORM(db) jorm = job.NewORM(db, orm, bridgeORM, keyStore, lggr, config.Database()) @@ -661,7 +661,7 @@ func Test_GetUnfinishedRuns_Keepers(t *testing.T) { config := configtest.NewTestGeneralConfig(t) lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) @@ -764,7 +764,7 @@ func Test_GetUnfinishedRuns_DirectRequest(t *testing.T) { config := configtest.NewTestGeneralConfig(t) lggr := logger.TestLogger(t) db := pgtest.NewSqlxDB(t) - keyStore := cltest.NewKeyStore(t, db, config.Database()) + keyStore := cltest.NewKeyStore(t, db) porm := pipeline.NewORM(db, lggr, config.JobPipeline().MaxSuccessfulRuns()) bridgeORM := bridges.NewORM(db) diff --git a/core/services/pipeline/runner_test.go b/core/services/pipeline/runner_test.go index f27a6b35348..e086d5297ef 100644 --- a/core/services/pipeline/runner_test.go +++ b/core/services/pipeline/runner_test.go @@ -43,7 +43,7 @@ import ( func newRunner(t testing.TB, db *sqlx.DB, bridgeORM bridges.ORM, cfg chainlink.GeneralConfig) (pipeline.Runner, *mocks.ORM) { lggr := logger.TestLogger(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) orm := mocks.NewORM(t) @@ -480,7 +480,7 @@ func Test_PipelineRunner_HandleFaultsPersistRun(t *testing.T) { }). Return(nil) cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) lggr := logger.TestLogger(t) @@ -521,7 +521,7 @@ func Test_PipelineRunner_ExecuteAndInsertFinishedRun_SavingTheSpec(t *testing.T) }). Return(nil) cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) lggr := logger.TestLogger(t) @@ -1002,7 +1002,7 @@ func Test_PipelineRunner_ExecuteRun(t *testing.T) { t.Run("uses cached *Pipeline if available", func(t *testing.T) { db := pgtest.NewSqlxDB(t) cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{DB: db, GeneralConfig: cfg, KeyStore: ethKeyStore}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) lggr := logger.TestLogger(t) diff --git a/core/services/promreporter/prom_reporter_test.go b/core/services/promreporter/prom_reporter_test.go index 9627b52f871..635b5b83c47 100644 --- a/core/services/promreporter/prom_reporter_test.go +++ b/core/services/promreporter/prom_reporter_test.go @@ -34,7 +34,7 @@ func newHead() evmtypes.Head { func newLegacyChainContainer(t *testing.T, db *sqlx.DB) legacyevm.LegacyChainContainer { config, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) - keyStore := cltest.NewKeyStore(t, db, dbConfig).Eth() + keyStore := cltest.NewKeyStore(t, db).Eth() ethClient := evmtest.NewEthClientMockWithDefaultChain(t) estimator := gas.NewEstimator(logger.TestLogger(t), ethClient, config, evmConfig.GasEstimator()) lggr := logger.TestLogger(t) @@ -95,9 +95,8 @@ func Test_PromReporter_OnNewLongestChain(t *testing.T) { t.Run("with unconfirmed evm.txes", func(t *testing.T) { db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) txStore := cltest.NewTestTxStore(t, db) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() _, fromAddress := cltest.MustInsertRandomKey(t, ethKeyStore) var subscribeCalls atomic.Int32 diff --git a/core/services/relay/evm/functions/contract_transmitter_test.go b/core/services/relay/evm/functions/contract_transmitter_test.go index fb50f6941b2..c0ca43e23ca 100644 --- a/core/services/relay/evm/functions/contract_transmitter_test.go +++ b/core/services/relay/evm/functions/contract_transmitter_test.go @@ -22,7 +22,6 @@ import ( txmmocks "github.com/smartcontractkit/chainlink/v2/core/chains/evm/txmgr/mocks" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/pgtest" "github.com/smartcontractkit/chainlink/v2/core/logger" "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/functions/encoding" @@ -38,8 +37,7 @@ func TestContractTransmitter_LatestConfigDigestAndEpoch(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() digestStr := "000130da6b9315bd59af6b0a3f5463c0d0a39e92eaa34cbcbdbace7b3bfcc776" lggr := logger.TestLogger(t) @@ -90,8 +88,7 @@ func TestContractTransmitter_Transmit_V1(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() contractVersion := uint32(1) configuredDestAddress, coordinatorAddress := testutils.NewAddress(), testutils.NewAddress() @@ -169,8 +166,7 @@ func TestContractTransmitter_Transmit_V1_CoordinatorMismatch(t *testing.T) { ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) - ethKeyStore := cltest.NewKeyStore(t, db, cfg.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() contractVersion := uint32(1) configuredDestAddress, coordinatorAddress1, coordinatorAddress2 := testutils.NewAddress(), testutils.NewAddress(), testutils.NewAddress() diff --git a/core/services/relay/evm/relayer_extender_test.go b/core/services/relay/evm/relayer_extender_test.go index af15461aee9..b9a6433c3a7 100644 --- a/core/services/relay/evm/relayer_extender_test.go +++ b/core/services/relay/evm/relayer_extender_test.go @@ -22,6 +22,7 @@ import ( func TestChainRelayExtenders(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) newId := testutils.NewRandomEVMChainID() cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -31,8 +32,8 @@ func TestChainRelayExtenders(t *testing.T) { c.EVM = append(c.EVM, &toml.EVMConfig{ChainID: ubig.New(newId), Enabled: &t, Chain: toml.Defaults(nil)}) }) db := pgtest.NewSqlxDB(t) - kst := cltest.NewKeyStore(t, db, cfg.Database()) - require.NoError(t, kst.Unlock(cltest.Password)) + kst := cltest.NewKeyStore(t, db) + require.NoError(t, kst.Unlock(ctx, cltest.Password)) opts := evmtest.NewChainRelayExtOpts(t, evmtest.TestChainOpts{DB: db, KeyStore: kst.Eth(), GeneralConfig: cfg}) opts.GenEthClient = func(*big.Int) evmclient.Client { diff --git a/core/services/vrf/delegate_test.go b/core/services/vrf/delegate_test.go index db9724179e7..6df91cef717 100644 --- a/core/services/vrf/delegate_test.go +++ b/core/services/vrf/delegate_test.go @@ -67,6 +67,7 @@ type vrfUniverse struct { } func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniverse { + ctx := testutils.Context(t) // Mock all chain interactions lb := log_mocks.NewBroadcaster(t) lb.On("AddDependents", 1).Maybe() @@ -80,7 +81,7 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv // Don't mock db interactions prm := pipeline.NewORM(db, lggr, cfg.JobPipeline().MaxSuccessfulRuns()) btORM := bridges.NewORM(db) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) _, dbConfig, evmConfig := txmgr.MakeTestConfigs(t) txm, err := txmgr.NewTxm(db, db, evmConfig, evmConfig.GasEstimator(), evmConfig.Transactions(), dbConfig, dbConfig.Listener(), ec, logger.TestLogger(t), nil, ks.Eth(), nil) orm := headtracker.NewORM(*testutils.FixtureChainID, db) @@ -90,12 +91,12 @@ func buildVrfUni(t *testing.T, db *sqlx.DB, cfg chainlink.GeneralConfig) vrfUniv relayExtenders := evmtest.NewChainRelayExtenders(t, evmtest.TestChainOpts{LogBroadcaster: lb, KeyStore: ks.Eth(), Client: ec, DB: db, GeneralConfig: cfg, TxManager: txm}) legacyChains := evmrelay.NewLegacyChainsFromRelayerExtenders(relayExtenders) pr := pipeline.NewRunner(prm, btORM, cfg.JobPipeline(), cfg.WebServer(), legacyChains, ks.Eth(), ks.VRF(), lggr, nil, nil) - require.NoError(t, ks.Unlock(testutils.Password)) + require.NoError(t, ks.Unlock(ctx, testutils.Password)) k, err2 := ks.Eth().Create(testutils.Context(t), testutils.FixtureChainID) require.NoError(t, err2) submitter := k.Address require.NoError(t, err) - vrfkey, err3 := ks.VRF().Create() + vrfkey, err3 := ks.VRF().Create(ctx) require.NoError(t, err3) return vrfUniverse{ @@ -559,11 +560,11 @@ decode_log->vrf->encode_tx->submit_tx func Test_CheckFromAddressesExist(t *testing.T) { t.Run("from addresses exist", func(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) lggr := logger.TestLogger(t) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) - require.NoError(t, ks.Unlock(testutils.Password)) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, testutils.Password)) var fromAddresses []string for i := 0; i < 3; i++ { @@ -587,11 +588,11 @@ func Test_CheckFromAddressesExist(t *testing.T) { }) t.Run("one of from addresses doesn't exist", func(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewTestGeneralConfig(t) lggr := logger.TestLogger(t) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) - require.NoError(t, ks.Unlock(testutils.Password)) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, testutils.Password)) var fromAddresses []string for i := 0; i < 3; i++ { diff --git a/core/services/vrf/proof/proof_response_test.go b/core/services/vrf/proof/proof_response_test.go index c547be2be2c..994ac80b5e2 100644 --- a/core/services/vrf/proof/proof_response_test.go +++ b/core/services/vrf/proof/proof_response_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/smartcontractkit/chainlink/v2/core/gethwrappers/generated/solidity_vrf_verifier_wrapper" - "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/configtest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" proof2 "github.com/smartcontractkit/chainlink/v2/core/services/vrf/proof" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -22,11 +22,11 @@ import ( ) func TestMarshaledProof(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) - cfg := configtest.NewGeneralConfig(t, nil) - keyStore := cltest.NewKeyStore(t, db, cfg.Database()) + keyStore := cltest.NewKeyStore(t, db) key := cltest.DefaultVRFKey - require.NoError(t, keyStore.VRF().Add(key)) + require.NoError(t, keyStore.VRF().Add(ctx, key)) blockHash := common.Hash{} blockNum := 0 preSeed := big.NewInt(1) diff --git a/core/services/vrf/v1/integration_test.go b/core/services/vrf/v1/integration_test.go index 1d11615950b..c28ad9ce3d0 100644 --- a/core/services/vrf/v1/integration_test.go +++ b/core/services/vrf/v1/integration_test.go @@ -233,7 +233,8 @@ func TestIntegration_VRF_WithBHS(t *testing.T) { } func createVRFJobRegisterKey(t *testing.T, u vrftesthelpers.CoordinatorUniverse, app *cltest.TestApplication, incomingConfs int) (job.Job, vrfkey.KeyV2) { - vrfKey, err := app.KeyStore.VRF().Create() + ctx := testutils.Context(t) + vrfKey, err := app.KeyStore.VRF().Create(ctx) require.NoError(t, err) jid := uuid.MustParse("96a8a26f-d426-4784-8d8f-fb387d4d8345") diff --git a/core/services/vrf/v2/integration_helpers_test.go b/core/services/vrf/v2/integration_helpers_test.go index 3d7a94ae833..2e0554fca96 100644 --- a/core/services/vrf/v2/integration_helpers_test.go +++ b/core/services/vrf/v2/integration_helpers_test.go @@ -1672,9 +1672,9 @@ func testMaliciousConsumer( app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, config, uni.backend, ownerKey) require.NoError(t, app.Start(ctx)) - err := app.GetKeyStore().Unlock(cltest.Password) + err := app.GetKeyStore().Unlock(ctx, cltest.Password) require.NoError(t, err) - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) jid := uuid.New() @@ -1796,7 +1796,7 @@ func testReplayOldRequestsOnStartUp( require.NoError(t, app.Start(ctx)) // Create VRF Key, register it to coordinator and export - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) registerProvingKeyHelper(t, uni, coordinator, vrfkey, &defaultMaxGasPrice) keyHash := vrfkey.PublicKey.MustHash() @@ -1833,7 +1833,7 @@ func testReplayOldRequestsOnStartUp( require.NoError(t, app.Start(ctx)) - vrfKey, err := app.GetKeyStore().VRF().Import(encodedVrfKey, testutils.Password) + vrfKey, err := app.GetKeyStore().VRF().Import(ctx, encodedVrfKey, testutils.Password) require.NoError(t, err) incomingConfs := 2 diff --git a/core/services/vrf/v2/integration_v2_plus_test.go b/core/services/vrf/v2/integration_v2_plus_test.go index 742ff99071c..b885473e488 100644 --- a/core/services/vrf/v2/integration_v2_plus_test.go +++ b/core/services/vrf/v2/integration_v2_plus_test.go @@ -847,6 +847,7 @@ func TestVRFV2PlusIntegration_TestMaliciousConsumer(t *testing.T) { } func TestVRFV2PlusIntegration_RequestCost(t *testing.T) { + ctx := testutils.Context(t) key := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, key, 1, false) @@ -854,7 +855,7 @@ func TestVRFV2PlusIntegration_RequestCost(t *testing.T) { app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, uni.backend, key) require.NoError(t, app.Start(testutils.Context(t))) - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey, &defaultMaxGasPrice) t.Run("non-proxied consumer", func(tt *testing.T) { @@ -1002,6 +1003,7 @@ func requestAndEstimateFulfillmentCost( } func TestVRFV2PlusIntegration_FulfillmentCost(t *testing.T) { + ctx := testutils.Context(t) key := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2PlusUniverse(t, key, 1, false) @@ -1009,7 +1011,7 @@ func TestVRFV2PlusIntegration_FulfillmentCost(t *testing.T) { app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, uni.backend, key) require.NoError(t, app.Start(testutils.Context(t))) - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey, &defaultMaxGasPrice) diff --git a/core/services/vrf/v2/integration_v2_reverted_txns_test.go b/core/services/vrf/v2/integration_v2_reverted_txns_test.go index b8e6f5f9b05..dfee450b6a2 100644 --- a/core/services/vrf/v2/integration_v2_reverted_txns_test.go +++ b/core/services/vrf/v2/integration_v2_reverted_txns_test.go @@ -411,6 +411,7 @@ func createVRFJobsNew( chainID *big.Int, gasLanePrices ...*assets.Wei, ) (jobs []job.Job, vrfKeyIDs []string) { + ctx := testutils.Context(t) if len(gasLanePrices) != len(fromKeys) { t.Fatalf("must provide one gas lane price for each set of from addresses. len(gasLanePrices) != len(fromKeys) [%d != %d]", len(gasLanePrices), len(fromKeys)) @@ -422,7 +423,7 @@ func createVRFJobsNew( keyStrs = append(keyStrs, k.Address.String()) } - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) jid := uuid.New() diff --git a/core/services/vrf/v2/integration_v2_test.go b/core/services/vrf/v2/integration_v2_test.go index 0c81c3faca5..543ec943527 100644 --- a/core/services/vrf/v2/integration_v2_test.go +++ b/core/services/vrf/v2/integration_v2_test.go @@ -531,6 +531,7 @@ func createVRFJobs( batchEnabled bool, gasLanePrices ...*assets.Wei, ) (jobs []job.Job) { + ctx := testutils.Context(t) if len(gasLanePrices) != len(fromKeys) { t.Fatalf("must provide one gas lane price for each set of from addresses. len(gasLanePrices) != len(fromKeys) [%d != %d]", len(gasLanePrices), len(fromKeys)) @@ -542,7 +543,7 @@ func createVRFJobs( keyStrs = append(keyStrs, k.Address.String()) } - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) jid := uuid.New() @@ -1838,6 +1839,7 @@ func TestMaliciousConsumer(t *testing.T) { } func TestRequestCost(t *testing.T) { + ctx := testutils.Context(t) key := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, key, 1) @@ -1845,7 +1847,7 @@ func TestRequestCost(t *testing.T) { app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, uni.backend, key) require.NoError(t, app.Start(testutils.Context(t))) - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey, nil) t.Run("non-proxied consumer", func(tt *testing.T) { @@ -1943,6 +1945,7 @@ func TestMaxConsumersCost(t *testing.T) { } func TestFulfillmentCost(t *testing.T) { + ctx := testutils.Context(t) key := cltest.MustGenerateRandomKey(t) uni := newVRFCoordinatorV2Universe(t, key, 1) @@ -1950,7 +1953,7 @@ func TestFulfillmentCost(t *testing.T) { app := cltest.NewApplicationWithConfigV2AndKeyOnSimulatedBlockchain(t, cfg, uni.backend, key) require.NoError(t, app.Start(testutils.Context(t))) - vrfkey, err := app.GetKeyStore().VRF().Create() + vrfkey, err := app.GetKeyStore().VRF().Create(ctx) require.NoError(t, err) registerProvingKeyHelper(t, uni.coordinatorV2UniverseCommon, uni.rootContract, vrfkey, nil) @@ -2050,7 +2053,7 @@ func TestStartingCountsV1(t *testing.T) { ctx := testutils.Context(t) lggr := logger.TestLogger(t) txStore := txmgr.NewTxStore(db, logger.TestLogger(t)) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg.Database()) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) ec := evmclimocks.NewClient(t) ec.On("ConfiguredChainID").Return(testutils.SimulatedChainID) ec.On("LatestBlockHeight", mock.Anything).Return(big.NewInt(2), nil).Maybe() @@ -2067,7 +2070,7 @@ func TestStartingCountsV1(t *testing.T) { counts, err = listenerV1.GetStartingResponseCountsV1(testutils.Context(t)) require.NoError(t, err) assert.Equal(t, 0, len(counts)) - err = ks.Unlock(testutils.Password) + err = ks.Unlock(ctx, testutils.Password) require.NoError(t, err) k, err := ks.Eth().Create(testutils.Context(t), testutils.SimulatedChainID) require.NoError(t, err) diff --git a/core/services/vrf/v2/listener_v2_log_listener_test.go b/core/services/vrf/v2/listener_v2_log_listener_test.go index 15b0a5ecbe8..a393aec3ee3 100644 --- a/core/services/vrf/v2/listener_v2_log_listener_test.go +++ b/core/services/vrf/v2/listener_v2_log_listener_test.go @@ -64,6 +64,7 @@ func setupVRFLogPollerListenerTH(t *testing.T, finalityDepth, backfillBatchSize, rpcBatchSize, keepFinalizedBlocksDepth int64, mockChainUpdateFn func(*evmmocks.Chain, *vrfLogPollerListenerTH)) *vrfLogPollerListenerTH { + ctx := testutils.Context(t) lggr := logger.TestLogger(t) chainID := testutils.NewRandomEVMChainID() @@ -111,9 +112,8 @@ func setupVRFLogPollerListenerTH(t *testing.T, ec.Commit() // Log Poller Listener - cfg := pgtest.NewQConfig(false) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg) - require.NoError(t, ks.Unlock("blah")) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, "blah")) j, err := vrfcommon.ValidatedVRFSpec(testspecs.GenerateVRFSpec(testspecs.VRFSpecParams{ RequestedConfsDelay: 10, EVMChainID: chainID.String(), @@ -134,7 +134,6 @@ func setupVRFLogPollerListenerTH(t *testing.T, inflightCache: vrfcommon.NewInflightCache(10), chStop: make(chan struct{}), } - ctx := testutils.Context(t) // Filter registration is idempotent, so we can just call it every time // and retry on errors using the ticker. diff --git a/core/services/vrf/v2/listener_v2_test.go b/core/services/vrf/v2/listener_v2_test.go index 4e9e65bfafc..ac59f1fdb69 100644 --- a/core/services/vrf/v2/listener_v2_test.go +++ b/core/services/vrf/v2/listener_v2_test.go @@ -180,11 +180,11 @@ func addConfirmedEthTxNativePayment(t *testing.T, txStore txmgr.TestEvmTxStore, } func testMaybeSubtractReservedLink(t *testing.T, vrfVersion vrfcommon.Version) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - cfg := pgtest.NewQConfig(false) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg) - require.NoError(t, ks.Unlock("blah")) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, "blah")) chainID := testutils.SimulatedChainID k, err := ks.Eth().Create(testutils.Context(t), chainID) require.NoError(t, err) @@ -206,8 +206,6 @@ func testMaybeSubtractReservedLink(t *testing.T, vrfVersion vrfcommon.Version) { chain: chain, } - ctx := testutils.Context(t) - // Insert an unstarted eth tx with link metadata addEthTx(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion) start, err := listener.MaybeSubtractReservedLink(ctx, big.NewInt(100_000), chainID, subID, vrfVersion) @@ -262,11 +260,11 @@ func TestMaybeSubtractReservedLinkV2Plus(t *testing.T) { } func testMaybeSubtractReservedNative(t *testing.T, vrfVersion vrfcommon.Version) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - cfg := pgtest.NewQConfig(false) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg) - require.NoError(t, ks.Unlock("blah")) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, "blah")) chainID := testutils.SimulatedChainID k, err := ks.Eth().Create(testutils.Context(t), chainID) require.NoError(t, err) @@ -289,8 +287,6 @@ func testMaybeSubtractReservedNative(t *testing.T, vrfVersion vrfcommon.Version) chain: chain, } - ctx := testutils.Context(t) - // Insert an unstarted eth tx with native metadata addEthTxNativePayment(t, txstore, k.Address, txmgrcommon.TxUnstarted, "10000", subID, reqTxHash, vrfVersion) start, err := listener.MaybeSubtractReservedEth(ctx, big.NewInt(100_000), chainID, subID, vrfVersion) @@ -341,11 +337,11 @@ func TestMaybeSubtractReservedNativeV2Plus(t *testing.T) { } func TestMaybeSubtractReservedNativeV2(t *testing.T) { + ctx := testutils.Context(t) db := pgtest.NewSqlxDB(t) lggr := logger.TestLogger(t) - cfg := pgtest.NewQConfig(false) - ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr, cfg) - require.NoError(t, ks.Unlock("blah")) + ks := keystore.NewInMemory(db, utils.FastScryptParams, lggr) + require.NoError(t, ks.Unlock(ctx, "blah")) chainID := testutils.SimulatedChainID subID := new(big.Int).SetUint64(1) diff --git a/core/web/build_info_controller_test.go b/core/web/build_info_controller_test.go index 5a2b88fa0dc..05ae421bf23 100644 --- a/core/web/build_info_controller_test.go +++ b/core/web/build_info_controller_test.go @@ -5,18 +5,19 @@ import ( "strings" "testing" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" clhttptest "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/httptest" - - "github.com/stretchr/testify/require" ) func TestBuildInfoController_Show_APICredentials(t *testing.T) { t.Parallel() app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) @@ -32,8 +33,8 @@ func TestBuildInfoController_Show_APICredentials(t *testing.T) { func TestBuildInfoController_Show_NoCredentials(t *testing.T) { t.Parallel() - ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) + ctx := testutils.Context(t) require.NoError(t, app.Start(ctx)) client := clhttptest.NewTestLocalOnlyHTTPClient() diff --git a/core/web/cosmos_chains_controller_test.go b/core/web/cosmos_chains_controller_test.go index 5491b33c359..9aaa0dd9eeb 100644 --- a/core/web/cosmos_chains_controller_test.go +++ b/core/web/cosmos_chains_controller_test.go @@ -182,7 +182,8 @@ func setupCosmosChainsControllerTestV2(t *testing.T, cfgs ...*coscfg.TOMLConfig) c.EVM = nil }) app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) diff --git a/core/web/cosmos_keys_controller_test.go b/core/web/cosmos_keys_controller_test.go index 3b777de7b7c..1de64625dfa 100644 --- a/core/web/cosmos_keys_controller_test.go +++ b/core/web/cosmos_keys_controller_test.go @@ -40,7 +40,8 @@ func TestCosmosKeysController_Create_HappyPath(t *testing.T) { t.Parallel() app := cltest.NewApplicationEVMDisabled(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) keyStore := app.GetKeyStore() @@ -75,12 +76,13 @@ func TestCosmosKeysController_Delete_NonExistentCosmosKeyID(t *testing.T) { func TestCosmosKeysController_Delete_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) client, keyStore := setupCosmosKeysControllerTests(t) keys, _ := keyStore.Cosmos().GetAll() initialLength := len(keys) - key, _ := keyStore.Cosmos().Create() + key, _ := keyStore.Cosmos().Create(ctx) response, cleanup := client.Delete(fmt.Sprintf("/v2/keys/cosmos/%s", key.ID())) t.Cleanup(cleanup) @@ -93,10 +95,11 @@ func TestCosmosKeysController_Delete_HappyPath(t *testing.T) { func setupCosmosKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { t.Helper() + ctx := testutils.Context(t) app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.Cosmos().Add(cltest.DefaultCosmosKey)) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.Cosmos().Add(ctx, cltest.DefaultCosmosKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/csa_keys_controller.go b/core/web/csa_keys_controller.go index fc927c61b3c..f97e5751df0 100644 --- a/core/web/csa_keys_controller.go +++ b/core/web/csa_keys_controller.go @@ -34,7 +34,8 @@ func (ctrl *CSAKeysController) Index(c *gin.Context) { // Example: // "POST /keys/csa" func (ctrl *CSAKeysController) Create(c *gin.Context) { - key, err := ctrl.App.GetKeyStore().CSA().Create() + ctx := c.Request.Context() + key, err := ctrl.App.GetKeyStore().CSA().Create(ctx) if err != nil { if errors.Is(err, keystore.ErrCSAKeyExists) { jsonAPIError(c, http.StatusBadRequest, err) @@ -56,6 +57,7 @@ func (ctrl *CSAKeysController) Create(c *gin.Context) { // Import imports a CSA key func (ctrl *CSAKeysController) Import(c *gin.Context) { defer ctrl.App.GetLogger().ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -63,7 +65,7 @@ func (ctrl *CSAKeysController) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - key, err := ctrl.App.GetKeyStore().CSA().Import(bytes, oldPassword) + key, err := ctrl.App.GetKeyStore().CSA().Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/dkgencrypt_keys_controller_test.go b/core/web/dkgencrypt_keys_controller_test.go index 7100cbbb1cd..fde00eb6420 100644 --- a/core/web/dkgencrypt_keys_controller_test.go +++ b/core/web/dkgencrypt_keys_controller_test.go @@ -100,8 +100,9 @@ func setupDKGEncryptKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, t.Helper() app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.DKGEncrypt().Add(cltest.DefaultDKGEncryptKey)) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.DKGEncrypt().Add(ctx, cltest.DefaultDKGEncryptKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/dkgsign_keys_controller_test.go b/core/web/dkgsign_keys_controller_test.go index ed67d71a0d5..b253a36ccc3 100644 --- a/core/web/dkgsign_keys_controller_test.go +++ b/core/web/dkgsign_keys_controller_test.go @@ -100,8 +100,9 @@ func setupDKGSignKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, ke t.Helper() app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.DKGSign().Add(cltest.DefaultDKGSignKey)) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.DKGSign().Add(ctx, cltest.DefaultDKGSignKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/eth_keys_controller_test.go b/core/web/eth_keys_controller_test.go index bab987fbcc2..09a3eb5fa1e 100644 --- a/core/web/eth_keys_controller_test.go +++ b/core/web/eth_keys_controller_test.go @@ -30,6 +30,7 @@ import ( func TestETHKeysController_Index_Success(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -39,7 +40,7 @@ func TestETHKeysController_Index_Success(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled key k0, addr0 := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -55,7 +56,7 @@ func TestETHKeysController_Index_Success(t *testing.T) { ethClient.On("LINKBalance", mock.Anything, addr1, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr2, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) resp, cleanup := client.Get("/v2/keys/evm") @@ -83,6 +84,7 @@ func TestETHKeysController_Index_Success(t *testing.T) { func TestETHKeysController_Index_Errors(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -92,14 +94,14 @@ func TestETHKeysController_Index_Errors(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) _, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) ethClient.On("BalanceAt", mock.Anything, addr, mock.Anything).Return(nil, errors.New("fake error")).Once() ethClient.On("LINKBalance", mock.Anything, addr, mock.Anything).Return(nil, errors.New("fake error")).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) resp, cleanup := client.Get("/v2/keys/eth") @@ -121,6 +123,7 @@ func TestETHKeysController_Index_Errors(t *testing.T) { func TestETHKeysController_Index_Disabled(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -129,11 +132,11 @@ func TestETHKeysController_Index_Disabled(t *testing.T) { app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) _, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) resp, cleanup := client.Get("/v2/keys/eth") @@ -168,7 +171,8 @@ func TestETHKeysController_Index_NotDev(t *testing.T) { ethClient.On("LINKBalance", mock.Anything, mock.Anything, mock.Anything).Return(assets.NewLinkFromJuels(256), nil).Once() app := cltest.NewApplicationWithConfigAndKey(t, cfg, ethClient) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) resp, cleanup := client.Get("/v2/keys/eth") @@ -193,7 +197,8 @@ func TestETHKeysController_Index_NoAccounts(t *testing.T) { t.Parallel() app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) @@ -227,7 +232,8 @@ func TestETHKeysController_CreateSuccess(t *testing.T) { client := app.NewHTTPClient(nil) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) chainURL := url.URL{Path: "/v2/keys/evm"} query := chainURL.Query() @@ -250,6 +256,7 @@ func TestETHKeysController_CreateSuccess(t *testing.T) { func TestETHKeysController_ChainSuccess_UpdateNonce(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -258,7 +265,7 @@ func TestETHKeysController_ChainSuccess_UpdateNonce(t *testing.T) { c.EVM[0].BalanceMonitor.Enabled = ptr(false) }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled key key, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -266,7 +273,7 @@ func TestETHKeysController_ChainSuccess_UpdateNonce(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, addr, mock.Anything).Return(big.NewInt(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -292,6 +299,7 @@ func TestETHKeysController_ChainSuccess_UpdateNonce(t *testing.T) { func TestETHKeysController_ChainSuccess_Disable(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -301,7 +309,7 @@ func TestETHKeysController_ChainSuccess_Disable(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled key key, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -309,7 +317,7 @@ func TestETHKeysController_ChainSuccess_Disable(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, addr, mock.Anything).Return(big.NewInt(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -337,6 +345,7 @@ func TestETHKeysController_ChainSuccess_Disable(t *testing.T) { func TestETHKeysController_ChainSuccess_Enable(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -345,7 +354,7 @@ func TestETHKeysController_ChainSuccess_Enable(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // disabled key key, addr := cltest.RandomKey{Disabled: true}.MustInsert(t, app.KeyStore.Eth()) @@ -353,7 +362,7 @@ func TestETHKeysController_ChainSuccess_Enable(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, addr, mock.Anything).Return(big.NewInt(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -381,6 +390,7 @@ func TestETHKeysController_ChainSuccess_Enable(t *testing.T) { func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -390,7 +400,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled key key, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -398,7 +408,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { ethClient.On("BalanceAt", mock.Anything, addr, mock.Anything).Return(big.NewInt(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) chain := app.GetRelayers().LegacyEVMChains().Slice()[0] subject := uuid.New() @@ -454,6 +464,7 @@ func TestETHKeysController_ChainSuccess_ResetWithAbandon(t *testing.T) { func TestETHKeysController_ChainFailure_InvalidAbandon(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -466,9 +477,9 @@ func TestETHKeysController_ChainFailure_InvalidAbandon(t *testing.T) { // enabled key _, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -487,6 +498,7 @@ func TestETHKeysController_ChainFailure_InvalidAbandon(t *testing.T) { func TestETHKeysController_ChainFailure_InvalidEnabled(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -499,9 +511,9 @@ func TestETHKeysController_ChainFailure_InvalidEnabled(t *testing.T) { // enabled key _, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -520,6 +532,7 @@ func TestETHKeysController_ChainFailure_InvalidEnabled(t *testing.T) { func TestETHKeysController_ChainFailure_InvalidAddress(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -528,9 +541,9 @@ func TestETHKeysController_ChainFailure_InvalidAddress(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -548,6 +561,7 @@ func TestETHKeysController_ChainFailure_InvalidAddress(t *testing.T) { func TestETHKeysController_ChainFailure_MissingAddress(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -556,9 +570,9 @@ func TestETHKeysController_ChainFailure_MissingAddress(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -576,6 +590,7 @@ func TestETHKeysController_ChainFailure_MissingAddress(t *testing.T) { func TestETHKeysController_ChainFailure_InvalidChainID(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -584,9 +599,9 @@ func TestETHKeysController_ChainFailure_InvalidChainID(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -604,6 +619,7 @@ func TestETHKeysController_ChainFailure_InvalidChainID(t *testing.T) { func TestETHKeysController_ChainFailure_MissingChainID(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) @@ -613,12 +629,12 @@ func TestETHKeysController_ChainFailure_MissingChainID(t *testing.T) { }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled key _, addr := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/chain"} @@ -636,6 +652,7 @@ func TestETHKeysController_ChainFailure_MissingChainID(t *testing.T) { func TestETHKeysController_DeleteSuccess(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -643,7 +660,7 @@ func TestETHKeysController_DeleteSuccess(t *testing.T) { c.EVM[0].BalanceMonitor.Enabled = ptr(false) }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) // enabled keys key0, addr0 := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) @@ -654,7 +671,7 @@ func TestETHKeysController_DeleteSuccess(t *testing.T) { ethClient.On("LINKBalance", mock.Anything, addr0, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() ethClient.On("LINKBalance", mock.Anything, addr1, mock.Anything).Return(assets.NewLinkFromJuels(1), nil).Once() - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/" + addr0.Hex()} @@ -688,15 +705,16 @@ func TestETHKeysController_DeleteSuccess(t *testing.T) { func TestETHKeysController_DeleteFailure_InvalidAddress(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm" + "/bad_address"} @@ -709,15 +727,16 @@ func TestETHKeysController_DeleteFailure_InvalidAddress(t *testing.T) { func TestETHKeysController_DeleteFailure_KeyMissing(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.EVM[0].NonceAutoSync = ptr(false) c.EVM[0].BalanceMonitor.Enabled = ptr(false) }) app := cltest.NewApplicationWithConfig(t, cfg, ethClient) - require.NoError(t, app.KeyStore.Unlock(cltest.Password)) + require.NoError(t, app.KeyStore.Unlock(ctx, cltest.Password)) - require.NoError(t, app.Start(testutils.Context(t))) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) chainURL := url.URL{Path: "/v2/keys/evm/" + testutils.NewAddress().Hex()} diff --git a/core/web/evm_chains_controller_test.go b/core/web/evm_chains_controller_test.go index 5d31374cfb7..157978bdd46 100644 --- a/core/web/evm_chains_controller_test.go +++ b/core/web/evm_chains_controller_test.go @@ -202,7 +202,8 @@ func setupEVMChainsControllerTest(t *testing.T, cfg chainlink.GeneralConfig) *Te // Using this instead of `NewApplicationEVMDisabled` since we need the chain set to be loaded in the app // for the sake of the API endpoints to work properly app := cltest.NewApplicationWithConfig(t, cfg) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) diff --git a/core/web/evm_forwarders_controller_test.go b/core/web/evm_forwarders_controller_test.go index 031a1a61c03..38e8c2f91f0 100644 --- a/core/web/evm_forwarders_controller_test.go +++ b/core/web/evm_forwarders_controller_test.go @@ -30,7 +30,8 @@ func setupEVMForwardersControllerTest(t *testing.T, overrideFn func(c *chainlink // Using this instead of `NewApplicationEVMDisabled` since we need the chain set to be loaded in the app // for the sake of the API endpoints to work properly app := cltest.NewApplicationWithConfig(t, configtest.NewGeneralConfig(t, overrideFn)) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) diff --git a/core/web/evm_transactions_controller_test.go b/core/web/evm_transactions_controller_test.go index e6d186fbab3..a4dd21c9f03 100644 --- a/core/web/evm_transactions_controller_test.go +++ b/core/web/evm_transactions_controller_test.go @@ -22,12 +22,12 @@ func TestTransactionsController_Index_Success(t *testing.T) { t.Parallel() app := cltest.NewApplicationWithKey(t) - require.NoError(t, app.Start(testutils.Context(t))) ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) db := app.GetSqlxDB() txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) - ethKeyStore := cltest.NewKeyStore(t, db, app.Config.Database()).Eth() + ethKeyStore := cltest.NewKeyStore(t, db).Eth() client := app.NewHTTPClient(nil) _, from := cltest.MustInsertRandomKey(t, ethKeyStore) @@ -68,7 +68,8 @@ func TestTransactionsController_Index_Error(t *testing.T) { t.Parallel() app := cltest.NewApplicationWithKey(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) resp, cleanup := client.Get("/v2/transactions?size=TrainingDay") @@ -80,7 +81,8 @@ func TestTransactionsController_Show_Success(t *testing.T) { t.Parallel() app := cltest.NewApplicationWithKey(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) client := app.NewHTTPClient(nil) @@ -113,7 +115,8 @@ func TestTransactionsController_Show_NotFound(t *testing.T) { t.Parallel() app := cltest.NewApplicationWithKey(t) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) txStore := cltest.NewTestTxStore(t, app.GetSqlxDB()) client := app.NewHTTPClient(nil) diff --git a/core/web/jobs_controller_test.go b/core/web/jobs_controller_test.go index 5255cad75f3..9c7b529b6bf 100644 --- a/core/web/jobs_controller_test.go +++ b/core/web/jobs_controller_test.go @@ -77,6 +77,7 @@ func TestJobsController_Create_ValidationFailure_OffchainReportingSpec(t *testin } for _, tc := range tt { t.Run(tc.name, func(t *testing.T) { + ctx := testutils.Context(t) ta, client := setupJobsControllerTests(t) var address types.EIP55Address @@ -87,7 +88,7 @@ func TestJobsController_Create_ValidationFailure_OffchainReportingSpec(t *testin address = cltest.NewEIP55Address() } - require.NoError(t, ta.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, ta.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) sp := cltest.MinimalOCRNonBootstrapSpec(contractAddress, address, tc.pid, tc.kb) body, _ := json.Marshal(web.CreateJobRequest{ @@ -104,8 +105,9 @@ func TestJobsController_Create_ValidationFailure_OffchainReportingSpec(t *testin } func TestJobController_Create_DirectRequest_Fast(t *testing.T) { + ctx := testutils.Context(t) app, client := setupJobsControllerTests(t) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) n := 10 @@ -137,9 +139,10 @@ func mustInt32FromString(t *testing.T, s string) int32 { } func TestJobController_Create_HappyPath(t *testing.T) { + ctx := testutils.Context(t) app, client := setupJobsControllerTests(t) b1, b2 := setupBridges(t, app.GetSqlxDB(), app.GetConfig().Database()) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) var pks []vrfkey.KeyV2 var k []p2pkey.KeyV2 { @@ -477,7 +480,6 @@ targets: func TestJobsController_Create_WebhookSpec(t *testing.T) { app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) - t.Cleanup(func() { assert.NoError(t, app.Stop()) }) _, fetchBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) _, submitBridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) @@ -608,6 +610,7 @@ func TestJobsController_Show_NonExistentID(t *testing.T) { } func TestJobsController_Update_HappyPath(t *testing.T) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.OCR.Enabled = ptr(true) c.P2P.V2.Enabled = ptr(true) @@ -616,7 +619,7 @@ func TestJobsController_Update_HappyPath(t *testing.T) { }) app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(testutils.Context(t))) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) @@ -680,7 +683,7 @@ func TestJobsController_Update_NonExistentID(t *testing.T) { }) app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) @@ -766,11 +769,12 @@ func setupJobsControllerTests(t *testing.T) (ta *cltest.TestApplication, cc clte }) ec := setupEthClientForControllerTests(t) app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey, ec) - require.NoError(t, app.Start(testutils.Context(t))) + ctx := testutils.Context(t) + require.NoError(t, app.Start(ctx)) client := app.NewHTTPClient(nil) vrfKeyStore := app.GetKeyStore().VRF() - _, err := vrfKeyStore.Create() + _, err := vrfKeyStore.Create(ctx) require.NoError(t, err) return app, client } @@ -793,7 +797,7 @@ func setupJobSpecsControllerTestsWithJobs(t *testing.T) (*cltest.TestApplication }) app := cltest.NewApplicationWithConfigAndKey(t, cfg, cltest.DefaultP2PKey) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(ctx)) _, bridge := cltest.MustCreateBridge(t, app.GetSqlxDB(), cltest.BridgeOpts{}) diff --git a/core/web/keys_controller.go b/core/web/keys_controller.go index 66fd596e719..ca7ef5e134a 100644 --- a/core/web/keys_controller.go +++ b/core/web/keys_controller.go @@ -1,6 +1,7 @@ package web import ( + "context" "fmt" "io" "net/http" @@ -16,9 +17,9 @@ import ( type Keystore[K keystore.Key] interface { Get(id string) (K, error) GetAll() ([]K, error) - Create() (K, error) - Delete(id string) (K, error) - Import(keyJSON []byte, password string) (K, error) + Create(context.Context) (K, error) + Delete(ctx context.Context, id string) (K, error) + Import(ctx context.Context, keyJSON []byte, password string) (K, error) Export(id string, password string) ([]byte, error) } @@ -73,7 +74,8 @@ func (kc *keysController[K, R]) Index(c *gin.Context) { } func (kc *keysController[K, R]) Create(c *gin.Context) { - key, err := kc.ks.Create() + ctx := c.Request.Context() + key, err := kc.ks.Create(ctx) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -88,13 +90,14 @@ func (kc *keysController[K, R]) Create(c *gin.Context) { } func (kc *keysController[K, R]) Delete(c *gin.Context) { + ctx := c.Request.Context() keyID := c.Param("keyID") key, err := kc.ks.Get(keyID) if err != nil { jsonAPIError(c, http.StatusNotFound, err) return } - _, err = kc.ks.Delete(key.ID()) + _, err = kc.ks.Delete(ctx, key.ID()) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -110,6 +113,7 @@ func (kc *keysController[K, R]) Delete(c *gin.Context) { func (kc *keysController[K, R]) Import(c *gin.Context) { defer kc.lggr.ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -117,7 +121,7 @@ func (kc *keysController[K, R]) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - key, err := kc.ks.Import(bytes, oldPassword) + key, err := kc.ks.Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/loop_registry_test.go b/core/web/loop_registry_test.go index 93eda32d0e8..f6c71faca50 100644 --- a/core/web/loop_registry_test.go +++ b/core/web/loop_registry_test.go @@ -62,6 +62,7 @@ func (m *mockLoopImpl) run() { } func TestLoopRegistry(t *testing.T) { + ctx := testutils.Context(t) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.OCR.Enabled = ptr(true) c.P2P.V2.Enabled = ptr(true) @@ -80,7 +81,7 @@ func TestLoopRegistry(t *testing.T) { model.LabelSet{"__metrics_path__": model.LabelValue(expectedLooppEndPoint)}, } - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) require.NoError(t, app.Start(testutils.Context(t))) // register a mock loop diff --git a/core/web/ocr2_keys_controller.go b/core/web/ocr2_keys_controller.go index 22109e90cba..2c4fcd19203 100644 --- a/core/web/ocr2_keys_controller.go +++ b/core/web/ocr2_keys_controller.go @@ -34,8 +34,9 @@ func (ocr2kc *OCR2KeysController) Index(c *gin.Context) { // Example: // "POST /keys/ocr" func (ocr2kc *OCR2KeysController) Create(c *gin.Context) { + ctx := c.Request.Context() chainType := chaintype.ChainType(c.Param("chainType")) - key, err := ocr2kc.App.GetKeyStore().OCR2().Create(chainType) + key, err := ocr2kc.App.GetKeyStore().OCR2().Create(ctx, chainType) if errors.Is(errors.Cause(err), chaintype.ErrInvalidChainType) { jsonAPIError(c, http.StatusBadRequest, err) return @@ -60,13 +61,14 @@ func (ocr2kc *OCR2KeysController) Create(c *gin.Context) { // Example: // "DELETE /keys/ocr/:keyID" func (ocr2kc *OCR2KeysController) Delete(c *gin.Context) { + ctx := c.Request.Context() id := c.Param("keyID") key, err := ocr2kc.App.GetKeyStore().OCR2().Get(id) if err != nil { jsonAPIError(c, http.StatusNotFound, err) return } - err = ocr2kc.App.GetKeyStore().OCR2().Delete(id) + err = ocr2kc.App.GetKeyStore().OCR2().Delete(ctx, id) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -81,6 +83,7 @@ func (ocr2kc *OCR2KeysController) Delete(c *gin.Context) { // "Post /keys/ocr/import" func (ocr2kc *OCR2KeysController) Import(c *gin.Context) { defer ocr2kc.App.GetLogger().ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -88,7 +91,7 @@ func (ocr2kc *OCR2KeysController) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - keyBundle, err := ocr2kc.App.GetKeyStore().OCR2().Import(bytes, oldPassword) + keyBundle, err := ocr2kc.App.GetKeyStore().OCR2().Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/ocr2_keys_controller_test.go b/core/web/ocr2_keys_controller_test.go index 815ae3ac20b..a8f480a1520 100644 --- a/core/web/ocr2_keys_controller_test.go +++ b/core/web/ocr2_keys_controller_test.go @@ -81,11 +81,12 @@ func TestOCR2KeysController_Delete_NonExistentOCRKeyID(t *testing.T) { } func TestOCR2KeysController_Delete_HappyPath(t *testing.T) { + ctx := testutils.Context(t) client, OCRKeyStore := setupOCR2KeysControllerTests(t) keys, _ := OCRKeyStore.GetAll() initialLength := len(keys) - key, _ := OCRKeyStore.Create("evm") + key, _ := OCRKeyStore.Create(ctx, "evm") response, cleanup := client.Delete("/v2/keys/ocr2/" + key.ID()) t.Cleanup(cleanup) @@ -98,12 +99,13 @@ func TestOCR2KeysController_Delete_HappyPath(t *testing.T) { func setupOCR2KeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.OCR2) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) client := app.NewHTTPClient(nil) - require.NoError(t, app.KeyStore.OCR2().Add(cltest.DefaultOCR2Key)) + require.NoError(t, app.KeyStore.OCR2().Add(ctx, cltest.DefaultOCR2Key)) return client, app.GetKeyStore().OCR2() } diff --git a/core/web/ocr_keys_controller.go b/core/web/ocr_keys_controller.go index 12eaa76372c..9be5dbf33d9 100644 --- a/core/web/ocr_keys_controller.go +++ b/core/web/ocr_keys_controller.go @@ -32,7 +32,8 @@ func (ocrkc *OCRKeysController) Index(c *gin.Context) { // Example: // "POST /keys/ocr" func (ocrkc *OCRKeysController) Create(c *gin.Context) { - key, err := ocrkc.App.GetKeyStore().OCR().Create() + ctx := c.Request.Context() + key, err := ocrkc.App.GetKeyStore().OCR().Create(ctx) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -50,13 +51,14 @@ func (ocrkc *OCRKeysController) Create(c *gin.Context) { // "DELETE /keys/ocr/:keyID" // "DELETE /keys/ocr/:keyID?hard=true" func (ocrkc *OCRKeysController) Delete(c *gin.Context) { + ctx := c.Request.Context() id := c.Param("keyID") key, err := ocrkc.App.GetKeyStore().OCR().Get(id) if err != nil { jsonAPIError(c, http.StatusNotFound, err) return } - _, err = ocrkc.App.GetKeyStore().OCR().Delete(id) + _, err = ocrkc.App.GetKeyStore().OCR().Delete(ctx, id) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -71,6 +73,7 @@ func (ocrkc *OCRKeysController) Delete(c *gin.Context) { // "Post /keys/ocr/import" func (ocrkc *OCRKeysController) Import(c *gin.Context) { defer ocrkc.App.GetLogger().ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -78,7 +81,7 @@ func (ocrkc *OCRKeysController) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - encryptedOCRKeyBundle, err := ocrkc.App.GetKeyStore().OCR().Import(bytes, oldPassword) + encryptedOCRKeyBundle, err := ocrkc.App.GetKeyStore().OCR().Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/ocr_keys_controller_test.go b/core/web/ocr_keys_controller_test.go index 31422f47c0c..82a0b9ebc2d 100644 --- a/core/web/ocr_keys_controller_test.go +++ b/core/web/ocr_keys_controller_test.go @@ -69,11 +69,12 @@ func TestOCRKeysController_Delete_NonExistentOCRKeyID(t *testing.T) { } func TestOCRKeysController_Delete_HappyPath(t *testing.T) { + ctx := testutils.Context(t) client, OCRKeyStore := setupOCRKeysControllerTests(t) keys, _ := OCRKeyStore.GetAll() initialLength := len(keys) - key, _ := OCRKeyStore.Create() + key, _ := OCRKeyStore.Create(ctx) response, cleanup := client.Delete("/v2/keys/ocr/" + key.ID()) t.Cleanup(cleanup) @@ -86,12 +87,13 @@ func TestOCRKeysController_Delete_HappyPath(t *testing.T) { func setupOCRKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.OCR) { t.Parallel() + ctx := testutils.Context(t) app := cltest.NewApplicationEVMDisabled(t) require.NoError(t, app.Start(testutils.Context(t))) client := app.NewHTTPClient(nil) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) return client, app.GetKeyStore().OCR() } diff --git a/core/web/p2p_keys_controller.go b/core/web/p2p_keys_controller.go index bbe9d83f741..042f44b7bc5 100644 --- a/core/web/p2p_keys_controller.go +++ b/core/web/p2p_keys_controller.go @@ -35,7 +35,8 @@ const keyType = "Ed25519" // Example: // "POST /keys/p2p" func (p2pkc *P2PKeysController) Create(c *gin.Context) { - key, err := p2pkc.App.GetKeyStore().P2P().Create() + ctx := c.Request.Context() + key, err := p2pkc.App.GetKeyStore().P2P().Create(ctx) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -56,6 +57,7 @@ func (p2pkc *P2PKeysController) Create(c *gin.Context) { // "DELETE /keys/p2p/:keyID" // "DELETE /keys/p2p/:keyID?hard=true" func (p2pkc *P2PKeysController) Delete(c *gin.Context) { + ctx := c.Request.Context() keyID, err := p2pkey.MakePeerID(c.Param("keyID")) if err != nil { jsonAPIError(c, http.StatusUnprocessableEntity, err) @@ -66,7 +68,7 @@ func (p2pkc *P2PKeysController) Delete(c *gin.Context) { jsonAPIError(c, http.StatusNotFound, err) return } - _, err = p2pkc.App.GetKeyStore().P2P().Delete(key.PeerID()) + _, err = p2pkc.App.GetKeyStore().P2P().Delete(ctx, key.PeerID()) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -85,6 +87,7 @@ func (p2pkc *P2PKeysController) Delete(c *gin.Context) { // "Post /keys/p2p/import" func (p2pkc *P2PKeysController) Import(c *gin.Context) { defer p2pkc.App.GetLogger().ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -92,7 +95,7 @@ func (p2pkc *P2PKeysController) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - key, err := p2pkc.App.GetKeyStore().P2P().Import(bytes, oldPassword) + key, err := p2pkc.App.GetKeyStore().P2P().Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return diff --git a/core/web/p2p_keys_controller_test.go b/core/web/p2p_keys_controller_test.go index df6f556fcb8..63cea5f0ea7 100644 --- a/core/web/p2p_keys_controller_test.go +++ b/core/web/p2p_keys_controller_test.go @@ -91,12 +91,13 @@ func TestP2PKeysController_Delete_InvalidPeerID(t *testing.T) { func TestP2PKeysController_Delete_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) client, keyStore := setupP2PKeysControllerTests(t) keys, _ := keyStore.P2P().GetAll() initialLength := len(keys) - key, _ := keyStore.P2P().Create() + key, _ := keyStore.P2P().Create(ctx) response, cleanup := client.Delete(fmt.Sprintf("/v2/keys/p2p/%s", key.ID())) t.Cleanup(cleanup) @@ -109,11 +110,12 @@ func TestP2PKeysController_Delete_HappyPath(t *testing.T) { func setupP2PKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { t.Helper() + ctx := testutils.Context(t) app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, app.KeyStore.P2P().Add(cltest.DefaultP2PKey)) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.P2P().Add(ctx, cltest.DefaultP2PKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/pipeline_runs_controller_test.go b/core/web/pipeline_runs_controller_test.go index a270a0a92b8..f6b4291a34f 100644 --- a/core/web/pipeline_runs_controller_test.go +++ b/core/web/pipeline_runs_controller_test.go @@ -250,6 +250,7 @@ func TestPipelineRunsController_ShowRun_InvalidID(t *testing.T) { func setupPipelineRunsControllerTests(t *testing.T) (cltest.HTTPClientCleaner, int32, []int64) { t.Parallel() + ctx := testutils.Context(t) ethClient := cltest.NewEthMocksWithStartupAssertions(t) ethClient.On("PendingNonceAt", mock.Anything, mock.Anything).Return(uint64(0), nil) cfg := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { @@ -261,8 +262,8 @@ func setupPipelineRunsControllerTests(t *testing.T) (cltest.HTTPClientCleaner, i c.EVM[0].BalanceMonitor.Enabled = ptr(false) }) app := cltest.NewApplicationWithConfigAndKey(t, cfg, ethClient, cltest.DefaultP2PKey) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) client := app.NewHTTPClient(nil) key, _ := cltest.MustInsertRandomKey(t, app.KeyStore.Eth()) diff --git a/core/web/resolver/csa_keys_test.go b/core/web/resolver/csa_keys_test.go index a94a934efa3..1048d9aa4bc 100644 --- a/core/web/resolver/csa_keys_test.go +++ b/core/web/resolver/csa_keys_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/csakey" @@ -109,7 +110,7 @@ func Test_CreateCSAKey(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.csa.On("Create").Return(fakeKey, nil) + f.Mocks.csa.On("Create", mock.Anything).Return(fakeKey, nil) f.Mocks.keystore.On("CSA").Return(f.Mocks.csa) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -120,7 +121,7 @@ func Test_CreateCSAKey(t *testing.T) { name: "csa key exists error", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.csa.On("Create").Return(csakey.KeyV2{}, keystore.ErrCSAKeyExists) + f.Mocks.csa.On("Create", mock.Anything).Return(csakey.KeyV2{}, keystore.ErrCSAKeyExists) f.Mocks.keystore.On("CSA").Return(f.Mocks.csa) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -180,7 +181,7 @@ func Test_DeleteCSAKey(t *testing.T) { before: func(f *gqlTestFramework) { f.App.On("GetKeyStore").Return(f.Mocks.keystore) f.Mocks.keystore.On("CSA").Return(f.Mocks.csa) - f.Mocks.csa.On("Delete", fakeKey.ID()).Return(fakeKey, nil) + f.Mocks.csa.On("Delete", mock.Anything, fakeKey.ID()).Return(fakeKey, nil) }, query: query, variables: variables, @@ -193,7 +194,7 @@ func Test_DeleteCSAKey(t *testing.T) { f.App.On("GetKeyStore").Return(f.Mocks.keystore) f.Mocks.keystore.On("CSA").Return(f.Mocks.csa) f.Mocks.csa. - On("Delete", fakeKey.ID()). + On("Delete", mock.Anything, fakeKey.ID()). Return(csakey.KeyV2{}, keystore.KeyNotFoundError{ID: fakeKey.ID(), KeyType: "CSA"}) }, query: query, diff --git a/core/web/resolver/mutation.go b/core/web/resolver/mutation.go index 551b8d8e89a..9b0f5e50a03 100644 --- a/core/web/resolver/mutation.go +++ b/core/web/resolver/mutation.go @@ -113,7 +113,7 @@ func (r *Resolver) CreateCSAKey(ctx context.Context) (*CreateCSAKeyPayloadResolv return nil, err } - key, err := r.App.GetKeyStore().CSA().Create() + key, err := r.App.GetKeyStore().CSA().Create(ctx) if err != nil { if errors.Is(err, keystore.ErrCSAKeyExists) { return NewCreateCSAKeyPayload(nil, err), nil @@ -137,7 +137,7 @@ func (r *Resolver) DeleteCSAKey(ctx context.Context, args struct { return nil, err } - key, err := r.App.GetKeyStore().CSA().Delete(string(args.ID)) + key, err := r.App.GetKeyStore().CSA().Delete(ctx, string(args.ID)) if err != nil { if errors.As(err, &keystore.KeyNotFoundError{}) { return NewDeleteCSAKeyPayload(csakey.KeyV2{}, err), nil @@ -561,7 +561,7 @@ func (r *Resolver) CreateOCRKeyBundle(ctx context.Context) (*CreateOCRKeyBundleP return nil, err } - key, err := r.App.GetKeyStore().OCR().Create() + key, err := r.App.GetKeyStore().OCR().Create(ctx) if err != nil { return nil, err } @@ -581,7 +581,7 @@ func (r *Resolver) DeleteOCRKeyBundle(ctx context.Context, args struct { return nil, err } - deletedKey, err := r.App.GetKeyStore().OCR().Delete(args.ID) + deletedKey, err := r.App.GetKeyStore().OCR().Delete(ctx, args.ID) if err != nil { if errors.As(err, &keystore.KeyNotFoundError{}) { return NewDeleteOCRKeyBundlePayloadResolver(ocrkey.KeyV2{}, err), nil @@ -636,7 +636,7 @@ func (r *Resolver) CreateP2PKey(ctx context.Context) (*CreateP2PKeyPayloadResolv return nil, err } - key, err := r.App.GetKeyStore().P2P().Create() + key, err := r.App.GetKeyStore().P2P().Create(ctx) if err != nil { return nil, err } @@ -665,7 +665,7 @@ func (r *Resolver) DeleteP2PKey(ctx context.Context, args struct { return nil, err } - key, err := r.App.GetKeyStore().P2P().Delete(keyID) + key, err := r.App.GetKeyStore().P2P().Delete(ctx, keyID) if err != nil { if errors.As(err, &keystore.KeyNotFoundError{}) { return NewDeleteP2PKeyPayload(p2pkey.KeyV2{}, err), nil @@ -686,7 +686,7 @@ func (r *Resolver) CreateVRFKey(ctx context.Context) (*CreateVRFKeyPayloadResolv return nil, err } - key, err := r.App.GetKeyStore().VRF().Create() + key, err := r.App.GetKeyStore().VRF().Create(ctx) if err != nil { return nil, err } @@ -708,7 +708,7 @@ func (r *Resolver) DeleteVRFKey(ctx context.Context, args struct { return nil, err } - key, err := r.App.GetKeyStore().VRF().Delete(string(args.ID)) + key, err := r.App.GetKeyStore().VRF().Delete(ctx, string(args.ID)) if err != nil { if errors.Is(errors.Cause(err), keystore.ErrMissingVRFKey) { return NewDeleteVRFKeyPayloadResolver(vrfkey.KeyV2{}, err), nil @@ -1206,7 +1206,7 @@ func (r *Resolver) CreateOCR2KeyBundle(ctx context.Context, args struct { ct := FromOCR2ChainType(args.ChainType) - key, err := r.App.GetKeyStore().OCR2().Create(chaintype.ChainType(ct)) + key, err := r.App.GetKeyStore().OCR2().Create(ctx, chaintype.ChainType(ct)) if err != nil { // Not covering the `chaintype.ErrInvalidChainType` since the GQL model would prevent a non-accepted chain-type from being received return nil, err @@ -1238,7 +1238,7 @@ func (r *Resolver) DeleteOCR2KeyBundle(ctx context.Context, args struct { return NewDeleteOCR2KeyBundlePayloadResolver(nil, err), nil } - err = r.App.GetKeyStore().OCR2().Delete(id) + err = r.App.GetKeyStore().OCR2().Delete(ctx, id) if err != nil { return nil, err } diff --git a/core/web/resolver/ocr2_keys_test.go b/core/web/resolver/ocr2_keys_test.go index 35ee1925cdb..fc82d070dd9 100644 --- a/core/web/resolver/ocr2_keys_test.go +++ b/core/web/resolver/ocr2_keys_test.go @@ -8,13 +8,13 @@ import ( gqlerrors "github.com/graph-gophers/graphql-go/errors" "github.com/pkg/errors" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils/keystest" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/chaintype" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocr2key" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestResolver_GetOCR2KeyBundles(t *testing.T) { @@ -151,7 +151,7 @@ func TestResolver_CreateOCR2KeyBundle(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr2.On("Create", chaintype.ChainType("evm")).Return(fakeKey, nil) + f.Mocks.ocr2.On("Create", mock.Anything, chaintype.ChainType("evm")).Return(fakeKey, nil) f.Mocks.keystore.On("OCR2").Return(f.Mocks.ocr2) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -163,7 +163,7 @@ func TestResolver_CreateOCR2KeyBundle(t *testing.T) { name: "generic error on Create()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr2.On("Create", chaintype.ChainType("evm")).Return(nil, gError) + f.Mocks.ocr2.On("Create", mock.Anything, chaintype.ChainType("evm")).Return(nil, gError) f.Mocks.keystore.On("OCR2").Return(f.Mocks.ocr2) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -239,7 +239,7 @@ func TestResolver_DeleteOCR2KeyBundle(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr2.On("Delete", fakeKey.ID()).Return(nil) + f.Mocks.ocr2.On("Delete", mock.Anything, fakeKey.ID()).Return(nil) f.Mocks.ocr2.On("Get", fakeKey.ID()).Return(fakeKey, nil) f.Mocks.keystore.On("OCR2").Return(f.Mocks.ocr2) f.App.On("GetKeyStore").Return(f.Mocks.keystore) @@ -269,7 +269,7 @@ func TestResolver_DeleteOCR2KeyBundle(t *testing.T) { name: "generic error on Delete()", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr2.On("Delete", fakeKey.ID()).Return(gError) + f.Mocks.ocr2.On("Delete", mock.Anything, fakeKey.ID()).Return(gError) f.Mocks.ocr2.On("Get", fakeKey.ID()).Return(fakeKey, nil) f.Mocks.keystore.On("OCR2").Return(f.Mocks.ocr2) f.App.On("GetKeyStore").Return(f.Mocks.keystore) diff --git a/core/web/resolver/ocr_test.go b/core/web/resolver/ocr_test.go index d1a0351842d..5ca56c4bd04 100644 --- a/core/web/resolver/ocr_test.go +++ b/core/web/resolver/ocr_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/ocrkey" @@ -105,7 +106,7 @@ func TestResolver_OCRCreateBundle(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr.On("Create").Return(fakeKey, nil) + f.Mocks.ocr.On("Create", mock.Anything).Return(fakeKey, nil) f.Mocks.keystore.On("OCR").Return(f.Mocks.ocr) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -163,7 +164,7 @@ func TestResolver_OCRDeleteBundle(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.ocr.On("Delete", fakeKey.ID()).Return(fakeKey, nil) + f.Mocks.ocr.On("Delete", mock.Anything, fakeKey.ID()).Return(fakeKey, nil) f.Mocks.keystore.On("OCR").Return(f.Mocks.ocr) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -176,7 +177,7 @@ func TestResolver_OCRDeleteBundle(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.Mocks.ocr. - On("Delete", fakeKey.ID()). + On("Delete", mock.Anything, fakeKey.ID()). Return(ocrkey.KeyV2{}, keystore.KeyNotFoundError{ID: "helloWorld", KeyType: "OCR"}) f.Mocks.keystore.On("OCR").Return(f.Mocks.ocr) f.App.On("GetKeyStore").Return(f.Mocks.keystore) diff --git a/core/web/resolver/p2p_test.go b/core/web/resolver/p2p_test.go index e2470f7fac5..6502ffc821a 100644 --- a/core/web/resolver/p2p_test.go +++ b/core/web/resolver/p2p_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/p2pkey" @@ -102,7 +103,7 @@ func TestResolver_CreateP2PKey(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.p2p.On("Create").Return(fakeKey, nil) + f.Mocks.p2p.On("Create", mock.Anything).Return(fakeKey, nil) f.Mocks.keystore.On("P2P").Return(f.Mocks.p2p) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -163,7 +164,7 @@ func TestResolver_DeleteP2PKey(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.p2p.On("Delete", peerID).Return(fakeKey, nil) + f.Mocks.p2p.On("Delete", mock.Anything, peerID).Return(fakeKey, nil) f.Mocks.keystore.On("P2P").Return(f.Mocks.p2p) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -176,7 +177,7 @@ func TestResolver_DeleteP2PKey(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.Mocks.p2p. - On("Delete", peerID). + On("Delete", mock.Anything, peerID). Return( p2pkey.KeyV2{}, keystore.KeyNotFoundError{ID: peerID.String(), KeyType: "P2P"}, diff --git a/core/web/resolver/vrf_test.go b/core/web/resolver/vrf_test.go index e1ee73b9984..5101bc5937b 100644 --- a/core/web/resolver/vrf_test.go +++ b/core/web/resolver/vrf_test.go @@ -8,6 +8,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/services/keystore/keys/vrfkey" @@ -198,7 +199,7 @@ func TestResolver_CreateVRFKey(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.vrf.On("Create").Return(fakeKey, nil) + f.Mocks.vrf.On("Create", mock.Anything).Return(fakeKey, nil) f.Mocks.keystore.On("VRF").Return(f.Mocks.vrf) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -261,7 +262,7 @@ func TestResolver_DeleteVRFKey(t *testing.T) { name: "success", authenticated: true, before: func(f *gqlTestFramework) { - f.Mocks.vrf.On("Delete", fakeKey.PublicKey.String()).Return(fakeKey, nil) + f.Mocks.vrf.On("Delete", mock.Anything, fakeKey.PublicKey.String()).Return(fakeKey, nil) f.Mocks.keystore.On("VRF").Return(f.Mocks.vrf) f.App.On("GetKeyStore").Return(f.Mocks.keystore) }, @@ -274,7 +275,7 @@ func TestResolver_DeleteVRFKey(t *testing.T) { authenticated: true, before: func(f *gqlTestFramework) { f.Mocks.vrf. - On("Delete", fakeKey.PublicKey.String()). + On("Delete", mock.Anything, fakeKey.PublicKey.String()). Return(vrfkey.KeyV2{}, errors.Wrapf( keystore.ErrMissingVRFKey, "unable to find VRF key with id %s", diff --git a/core/web/solana_keys_controller_test.go b/core/web/solana_keys_controller_test.go index 94b11207c92..b71f8287d0f 100644 --- a/core/web/solana_keys_controller_test.go +++ b/core/web/solana_keys_controller_test.go @@ -5,15 +5,15 @@ import ( "net/http" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" "github.com/smartcontractkit/chainlink/v2/core/services/keystore" "github.com/smartcontractkit/chainlink/v2/core/web" "github.com/smartcontractkit/chainlink/v2/core/web/presenters" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func TestSolanaKeysController_Index_HappyPath(t *testing.T) { @@ -75,12 +75,13 @@ func TestSolanaKeysController_Delete_NonExistentSolanaKeyID(t *testing.T) { func TestSolanaKeysController_Delete_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) client, keyStore := setupSolanaKeysControllerTests(t) keys, _ := keyStore.Solana().GetAll() initialLength := len(keys) - key, _ := keyStore.Solana().Create() + key, _ := keyStore.Solana().Create(ctx) response, cleanup := client.Delete(fmt.Sprintf("/v2/keys/solana/%s", key.ID())) t.Cleanup(cleanup) @@ -93,11 +94,12 @@ func TestSolanaKeysController_Delete_HappyPath(t *testing.T) { func setupSolanaKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { t.Helper() + ctx := testutils.Context(t) app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, app.KeyStore.Solana().Add(cltest.DefaultSolanaKey)) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.Solana().Add(ctx, cltest.DefaultSolanaKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/starknet_keys_controller_test.go b/core/web/starknet_keys_controller_test.go index 9215fb8f9c5..05f611f2f22 100644 --- a/core/web/starknet_keys_controller_test.go +++ b/core/web/starknet_keys_controller_test.go @@ -75,12 +75,13 @@ func TestStarkNetKeysController_Delete_NonExistentStarkNetKeyID(t *testing.T) { func TestStarkNetKeysController_Delete_HappyPath(t *testing.T) { t.Parallel() + ctx := testutils.Context(t) client, keyStore := setupStarkNetKeysControllerTests(t) keys, _ := keyStore.StarkNet().GetAll() initialLength := len(keys) - key, _ := keyStore.StarkNet().Create() + key, _ := keyStore.StarkNet().Create(ctx) response, cleanup := client.Delete(fmt.Sprintf("/v2/keys/starknet/%s", key.ID())) t.Cleanup(cleanup) @@ -93,11 +94,12 @@ func TestStarkNetKeysController_Delete_HappyPath(t *testing.T) { func setupStarkNetKeysControllerTests(t *testing.T) (cltest.HTTPClientCleaner, keystore.Master) { t.Helper() + ctx := testutils.Context(t) app := cltest.NewApplication(t) - require.NoError(t, app.Start(testutils.Context(t))) - require.NoError(t, app.KeyStore.OCR().Add(cltest.DefaultOCRKey)) - require.NoError(t, app.KeyStore.StarkNet().Add(cltest.DefaultStarkNetKey)) + require.NoError(t, app.Start(ctx)) + require.NoError(t, app.KeyStore.OCR().Add(ctx, cltest.DefaultOCRKey)) + require.NoError(t, app.KeyStore.StarkNet().Add(ctx, cltest.DefaultStarkNetKey)) client := app.NewHTTPClient(nil) diff --git a/core/web/vrf_keys_controller.go b/core/web/vrf_keys_controller.go index a54a3f9d596..567b8acc995 100644 --- a/core/web/vrf_keys_controller.go +++ b/core/web/vrf_keys_controller.go @@ -32,7 +32,8 @@ func (vrfkc *VRFKeysController) Index(c *gin.Context) { // Example: // "POST /keys/vrf" func (vrfkc *VRFKeysController) Create(c *gin.Context) { - pk, err := vrfkc.App.GetKeyStore().VRF().Create() + ctx := c.Request.Context() + pk, err := vrfkc.App.GetKeyStore().VRF().Create(ctx) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -53,13 +54,14 @@ func (vrfkc *VRFKeysController) Create(c *gin.Context) { // "DELETE /keys/vrf/:keyID" // "DELETE /keys/vrf/:keyID?hard=true" func (vrfkc *VRFKeysController) Delete(c *gin.Context) { + ctx := c.Request.Context() keyID := c.Param("keyID") key, err := vrfkc.App.GetKeyStore().VRF().Get(keyID) if err != nil { jsonAPIError(c, http.StatusNotFound, err) return } - _, err = vrfkc.App.GetKeyStore().VRF().Delete(keyID) + _, err = vrfkc.App.GetKeyStore().VRF().Delete(ctx, keyID) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return @@ -78,6 +80,7 @@ func (vrfkc *VRFKeysController) Delete(c *gin.Context) { // "Post /keys/vrf/import" func (vrfkc *VRFKeysController) Import(c *gin.Context) { defer vrfkc.App.GetLogger().ErrorIfFn(c.Request.Body.Close, "Error closing Import request body") + ctx := c.Request.Context() bytes, err := io.ReadAll(c.Request.Body) if err != nil { @@ -85,7 +88,7 @@ func (vrfkc *VRFKeysController) Import(c *gin.Context) { return } oldPassword := c.Query("oldpassword") - key, err := vrfkc.App.GetKeyStore().VRF().Import(bytes, oldPassword) + key, err := vrfkc.App.GetKeyStore().VRF().Import(ctx, bytes, oldPassword) if err != nil { jsonAPIError(c, http.StatusInternalServerError, err) return From 9d359de09fa2400d4d2bb52aec7308c9f2b52d1a Mon Sep 17 00:00:00 2001 From: Ilja Pavlovs Date: Mon, 22 Apr 2024 12:39:22 +0300 Subject: [PATCH 26/26] VRF-1028: Add migration commands to VRF V2Plus superscripts (#12908) --- core/scripts/vrfv2plus/testnet/main.go | 18 ++++++++++ .../vrfv2plus/testnet/v2plusscripts/util.go | 35 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/core/scripts/vrfv2plus/testnet/main.go b/core/scripts/vrfv2plus/testnet/main.go index f42bebe952b..9c7d212fc82 100644 --- a/core/scripts/vrfv2plus/testnet/main.go +++ b/core/scripts/vrfv2plus/testnet/main.go @@ -597,6 +597,24 @@ func main() { tx, err := coordinator.DeregisterProvingKey(e.Owner, [2]*big.Int{pk.X, pk.Y}) helpers.PanicErr(err) helpers.ConfirmTXMined(context.Background(), e.Ec, tx, e.ChainID) + case "coordinator-register-migratable-coordinator": + coordinatorRegisterMigratableCoordinator := flag.NewFlagSet("coordinator-register-migratable-coordinator", flag.ExitOnError) + coordinatorAddress := coordinatorRegisterMigratableCoordinator.String("address", "", "coordinator address from which to register migratable coordinator") + coordinatorMigrateToAddress := coordinatorRegisterMigratableCoordinator.String("coordinator-migrate-to-address", "", "coordinator address to register in order for perform sub migration to") + helpers.ParseArgs(coordinatorRegisterMigratableCoordinator, os.Args[2:], "address", "coordinator-migrate-to-address") + coordinator, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(common.HexToAddress(*coordinatorAddress), e.Ec) + helpers.PanicErr(err) + v2plusscripts.RegisterMigratableCoordinator(e, *coordinator, common.HexToAddress(*coordinatorMigrateToAddress)) + case "coordinator-migrate-sub": + coordinatorMigrateSub := flag.NewFlagSet("coordinator-migrate-sub", flag.ExitOnError) + coordinatorAddress := coordinatorMigrateSub.String("address", "", "coordinator address from which to migrate a sub") + coordinatorMigrateToAddress := coordinatorMigrateSub.String("coordinator-migrate-to-address", "", "coordinator address to migrate sub to") + subID := coordinatorMigrateSub.String("sub-id", "", "sub-id") + helpers.ParseArgs(coordinatorMigrateSub, os.Args[2:], "address", "coordinator-migrate-to-address", "sub-id") + parsedSubID := parseUInt256String(*subID) + coordinator, err := vrf_coordinator_v2_5.NewVRFCoordinatorV25(common.HexToAddress(*coordinatorAddress), e.Ec) + helpers.PanicErr(err) + v2plusscripts.MigrateSub(e, *coordinator, common.HexToAddress(*coordinatorMigrateToAddress), parsedSubID) case "coordinator-subscription": coordinatorSub := flag.NewFlagSet("coordinator-subscription", flag.ExitOnError) address := coordinatorSub.String("address", "", "coordinator address") diff --git a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go index 8becb31239c..ae57c4caae5 100644 --- a/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go +++ b/core/scripts/vrfv2plus/testnet/v2plusscripts/util.go @@ -198,6 +198,41 @@ func RegisterCoordinatorProvingKey(e helpers.Environment, ) } +func RegisterMigratableCoordinator( + e helpers.Environment, + coordinator vrf_coordinator_v2_5.VRFCoordinatorV25, + coordinatorMigrateToAddress common.Address, +) { + tx, err := coordinator.RegisterMigratableCoordinator(e.Owner, coordinatorMigrateToAddress) + helpers.PanicErr(err) + helpers.ConfirmTXMined( + context.Background(), + e.Ec, + tx, + e.ChainID, + fmt.Sprintf("Coordinator %s registered migratable coordinator %s", coordinator.Address().String(), coordinatorMigrateToAddress.String()), + ) +} + +func MigrateSub( + e helpers.Environment, + coordinatorMigrateSubFrom vrf_coordinator_v2_5.VRFCoordinatorV25, + coordinatorMigrateSubTo common.Address, + subID *big.Int, +) { + tx, err := coordinatorMigrateSubFrom.Migrate(e.Owner, subID, coordinatorMigrateSubTo) + helpers.PanicErr(err) + helpers.ConfirmTXMined( + context.Background(), + e.Ec, + tx, + e.ChainID, + fmt.Sprintf("Sub Migrated from Coordinator: %s,", coordinatorMigrateSubFrom.Address().String()), + fmt.Sprintf("Sub Migrated TO Coordinator: %s,", coordinatorMigrateSubTo.String()), + fmt.Sprintf("Sub ID which was migrated: %s,", subID.String()), + ) +} + func WrapperDeploy( e helpers.Environment, link, linkEthFeed, coordinator common.Address, subID *big.Int,