diff --git a/.changeset/breezy-taxis-breathe.md b/.changeset/breezy-taxis-breathe.md new file mode 100644 index 00000000000..79ce1ae96bd --- /dev/null +++ b/.changeset/breezy-taxis-breathe.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Add json schema support to workflows diff --git a/.changeset/chilly-garlics-kneel.md b/.changeset/chilly-garlics-kneel.md new file mode 100644 index 00000000000..fc8b9425250 --- /dev/null +++ b/.changeset/chilly-garlics-kneel.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Fix error log formatting for in memory data source cache for juels fee per coin diff --git a/.changeset/few-swans-wonder.md b/.changeset/few-swans-wonder.md new file mode 100644 index 00000000000..d6c3be39653 --- /dev/null +++ b/.changeset/few-swans-wonder.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +small gas fix diff --git a/.changeset/hungry-impalas-jog.md b/.changeset/hungry-impalas-jog.md new file mode 100644 index 00000000000..efa23edabb2 --- /dev/null +++ b/.changeset/hungry-impalas-jog.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Added a tx simulation feature to the chain client to enable testing for zk out-of-counter (OOC) errors diff --git a/.changeset/odd-mugs-divide.md b/.changeset/odd-mugs-divide.md new file mode 100644 index 00000000000..8498593c6eb --- /dev/null +++ b/.changeset/odd-mugs-divide.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Set LINK native feed in VRFV2PlusWrapper to immutable diff --git a/.changeset/poor-melons-vanish.md b/.changeset/poor-melons-vanish.md new file mode 100644 index 00000000000..3b6d901b157 --- /dev/null +++ b/.changeset/poor-melons-vanish.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add the `pool_rpc_node_highest_finalized_block` metric that tracks the highest finalized block seen per RPC. If `FinalityTagEnabled = true`, a positive `NodePool.FinalizedBlockPollInterval` is needed to collect the metric. If the finality tag is not enabled, the metric is populated with a calculated latest finalized block based on the latest head and finality depth. diff --git a/.changeset/quick-berries-sin.md b/.changeset/quick-berries-sin.md new file mode 100644 index 00000000000..e8c348a3561 --- /dev/null +++ b/.changeset/quick-berries-sin.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +fix bug in auto2.3 withdrawERC20Fees diff --git a/.changeset/rude-paws-cross.md b/.changeset/rude-paws-cross.md new file mode 100644 index 00000000000..395a6d76244 --- /dev/null +++ b/.changeset/rude-paws-cross.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +L1Oracle handles OP Stack Ecotone encoded l1 gas price diff --git a/.changeset/shaggy-pots-pretend.md b/.changeset/shaggy-pots-pretend.md new file mode 100644 index 00000000000..644986ddb56 --- /dev/null +++ b/.changeset/shaggy-pots-pretend.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Add error log if juels fee per coin cache is over 24h old and lower other logs severity in cache to warn diff --git a/.changeset/silent-pets-sip.md b/.changeset/silent-pets-sip.md new file mode 100644 index 00000000000..ba2417f0922 --- /dev/null +++ b/.changeset/silent-pets-sip.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Exposing information about LogPoller finality violation via Healthy method. It's raised whenever LogPoller sees reorg deeper than the finality diff --git a/.changeset/silly-weeks-serve.md b/.changeset/silly-weeks-serve.md new file mode 100644 index 00000000000..0f7386e69fe --- /dev/null +++ b/.changeset/silly-weeks-serve.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +update starknet relayer to fix nonce issue. introduces optional api-key for starknet toml config. diff --git a/.changeset/smooth-monkeys-help.md b/.changeset/smooth-monkeys-help.md new file mode 100644 index 00000000000..23e44dd3032 --- /dev/null +++ b/.changeset/smooth-monkeys-help.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +upgraded transmission to 0.8.19 diff --git a/.changeset/strange-swans-compare.md b/.changeset/strange-swans-compare.md new file mode 100644 index 00000000000..a5690cc5d93 --- /dev/null +++ b/.changeset/strange-swans-compare.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +remove trailing slash diff --git a/.changeset/thick-apes-reply.md b/.changeset/thick-apes-reply.md new file mode 100644 index 00000000000..83a0232d7bb --- /dev/null +++ b/.changeset/thick-apes-reply.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +bug fixes in s_reserveAmount accounting diff --git a/.changeset/thin-coats-joke.md b/.changeset/thin-coats-joke.md new file mode 100644 index 00000000000..0cb6a0851e2 --- /dev/null +++ b/.changeset/thin-coats-joke.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +fix withdraw LINK bug in auto 2.3 diff --git a/.changeset/tiny-rabbits-crave.md b/.changeset/tiny-rabbits-crave.md new file mode 100644 index 00000000000..55b6f71c523 --- /dev/null +++ b/.changeset/tiny-rabbits-crave.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +Handle zkSync specific known transaction error diff --git a/.changeset/tiny-suns-end.md b/.changeset/tiny-suns-end.md new file mode 100644 index 00000000000..3bdd12ea362 --- /dev/null +++ b/.changeset/tiny-suns-end.md @@ -0,0 +1,5 @@ +--- +"chainlink": patch +--- + +add test for billing override diff --git a/.changeset/wicked-gorillas-sniff.md b/.changeset/wicked-gorillas-sniff.md new file mode 100644 index 00000000000..7efb85aa18e --- /dev/null +++ b/.changeset/wicked-gorillas-sniff.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +VRFV2PlusWrapper config refactor diff --git a/.changeset/witty-jeans-wave.md b/.changeset/witty-jeans-wave.md new file mode 100644 index 00000000000..e2a386384ab --- /dev/null +++ b/.changeset/witty-jeans-wave.md @@ -0,0 +1,5 @@ +--- +"chainlink": minor +--- + +Remove 0.6 and 0.7 Solidity source code diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index bb75e6b568b..650351f62d0 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -517,7 +517,7 @@ jobs: os: ubuntu-latest pyroscope_env: ci-smoke-vrf2-evm-simulated - name: vrfv2plus - nodes: 6 + nodes: 7 os: ubuntu-latest pyroscope_env: ci-smoke-vrf2plus-evm-simulated - name: forwarder_ocr diff --git a/.github/workflows/operator-ui-ci.yml b/.github/workflows/operator-ui-ci.yml index 14bc5b75f70..c71fd392683 100644 --- a/.github/workflows/operator-ui-ci.yml +++ b/.github/workflows/operator-ui-ci.yml @@ -2,6 +2,9 @@ name: Operator UI CI on: pull_request: +env: + TARGET_BRANCH_NAME: ${{ github.event.pull_request.base.ref }} + jobs: check-gql: permissions: @@ -37,10 +40,24 @@ jobs: with: url: ${{ secrets.AWS_INFRA_RELENG_TOKEN_ISSUER_LAMBDA_URL }} + - name: Checkout repository + uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 + + - name: Get operator-ui tag + id: get-operator-ui-tag + shell: bash + run: | + if [[ $TARGET_BRANCH_NAME == release/* ]]; then + TAG=$(cat ./operator_ui/TAG) + echo "TAG=$TAG" >> $GITHUB_OUTPUT + else + echo "TAG=main" >> $GITHUB_OUTPUT + fi + - uses: convictional/trigger-workflow-and-wait@f69fa9eedd3c62a599220f4d5745230e237904be #v1.6.5 with: owner: smartcontractkit repo: operator-ui github_token: ${{ steps.get-gh-token.outputs.access-token }} workflow_file_name: chainlink-ci.yml - client_payload: '{"ref": "${{ github.event.pull_request.head.sha }}"}' + client_payload: '{"ref": "${{ github.event.pull_request.head.sha }}", "tag": "${{ steps.get-operator-ui-tag.outputs.TAG }}"}' diff --git a/.github/workflows/solidity-foundry.yml b/.github/workflows/solidity-foundry.yml index d88de60a38b..18537116f90 100644 --- a/.github/workflows/solidity-foundry.yml +++ b/.github/workflows/solidity-foundry.yml @@ -21,12 +21,11 @@ jobs: filters: | src: - 'contracts/src/v0.8/**/*' - - 'contracts/test/v0.8/foundry/**/*' - '.github/workflows/solidity-foundry.yml' - 'contracts/foundry.toml' - 'contracts/gas-snapshots/*.gas-snapshot' - - '.gitmodules' - 'contracts/foundry-lib' + - '.gitmodules' tests: strategy: diff --git a/.github/workflows/solidity-hardhat.yml b/.github/workflows/solidity-hardhat.yml index 16f2c32e58e..d2211145c5b 100644 --- a/.github/workflows/solidity-hardhat.yml +++ b/.github/workflows/solidity-hardhat.yml @@ -25,7 +25,7 @@ jobs: with: filters: | src: - - 'contracts/src/!(v0.8/(llo-feeds|keystone|ccip)/**)/**/*' + - 'contracts/src/!(v0.8/(llo-feeds|keystone|ccip|functions|transmission)/**)/**/*' - 'contracts/test/**/*' - 'contracts/package.json' - 'contracts/pnpm-lock.yaml' @@ -56,72 +56,6 @@ jobs: this-job-name: Split Solidity Tests continue-on-error: true - solidity-coverage-splits: - needs: [changes, split-tests] - if: needs.changes.outputs.changes == 'true' - name: Solidity Coverage ${{ matrix.split.id }} ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} - strategy: - fail-fast: false - matrix: - split: ${{ fromJson(needs.split-tests.outputs.splits) }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - name: Setup Hardhat - uses: ./.github/actions/setup-hardhat - with: - namespace: coverage - - name: Run coverage - env: - SPLIT: ${{ matrix.split.coverageTests }} - shell: bash - run: pnpm coverage --testfiles "$SPLIT" - working-directory: contracts - - name: Push coverage - run: ./tools/bin/codecov -f ./contracts/coverage.json - - name: Rename coverage - run: mv ./contracts/coverage.json ./contracts/coverage-${{ matrix.split.idx }}.json - - name: Upload coverage - uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3 # v4.3.1 - with: - name: solidity-coverage-${{ matrix.split.idx }} - path: ./contracts/coverage-${{ matrix.split.idx }}.json - - name: Collect Metrics - id: collect-gha-metrics - uses: smartcontractkit/push-gha-metrics-action@0281b09807758be1dcc41651e44e62b353808c47 # v2.1.0 - with: - org-id: ${{ secrets.GRAFANA_INTERNAL_TENANT_ID }} - basic-auth: ${{ secrets.GRAFANA_INTERNAL_BASIC_AUTH }} - hostname: ${{ secrets.GRAFANA_INTERNAL_HOST }} - this-job-name: Solidity Coverage ${{ matrix.split.id }} - continue-on-error: true - - solidity-coverage: - needs: [changes, solidity-coverage-splits] - if: needs.changes.outputs.changes == 'true' - name: Solidity Coverage ${{ fromJSON('["(skipped)", ""]')[needs.changes.outputs.changes == 'true'] }} - runs-on: ubuntu-latest - steps: - - name: Checkout the repo - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2 - - name: Setup NodeJS - uses: ./.github/actions/setup-nodejs - - name: Make coverage directory - run: mkdir ./contracts/coverage-reports - - name: Download coverage - uses: actions/download-artifact@c850b930e6ba138125429b7e5c93fc707a7f8427 # v4.1.4 - with: - path: ./contracts/coverage-reports - - name: Display structure of downloaded files - run: ls -R coverage-reports - working-directory: contracts - - name: Generate merged report - run: pnpm istanbul report text text-summary - working-directory: contracts - solidity-splits: needs: [changes, split-tests] if: needs.changes.outputs.changes == 'true' diff --git a/.github/workflows/solidity.yml b/.github/workflows/solidity.yml index 1907aba5ebc..9d3a165bdea 100644 --- a/.github/workflows/solidity.yml +++ b/.github/workflows/solidity.yml @@ -26,15 +26,17 @@ jobs: - 'contracts/**/*' - '.github/workflows/solidity.yml' - '.github/workflows/solidity-foundry.yml' - old_sol: - - 'contracts/src/v0.6/**/*' - - 'contracts/src/v0.7/**/*' + read_only_sol: + - 'contracts/src/v0.8/interfaces/**/*' + - 'contracts/src/v0.8/automation/v1_2/**/*' + - 'contracts/src/v0.8/automation/v1_3/**/*' + - 'contracts/src/v0.8/automation/v2_0/**/*' - name: Fail if read-only files have changed - if: ${{ steps.changes.outputs.old_sol == 'true' }} + if: ${{ steps.changes.outputs.read_only_sol == 'true' }} run: | echo "One or more read-only Solidity file(s) has changed." - for file in ${{ steps.changes.outputs.old_sol_files }}; do + for file in ${{ steps.changes.outputs.read_only_sol_files }}; do echo "$file was changed" done exit 1 diff --git a/CODEOWNERS b/CODEOWNERS index 4e1051a0ed1..1f9eb93efc0 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 @smartcontractkit/foundations +/contracts/src/v0.8/operatorforwarder @RensR /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 diff --git a/common/client/mock_head_test.go b/common/client/mock_head_test.go index 747770480f5..e68a047e078 100644 --- a/common/client/mock_head_test.go +++ b/common/client/mock_head_test.go @@ -51,6 +51,24 @@ func (_m *mockHead) BlockNumber() int64 { return r0 } +// IsValid provides a mock function with given fields: +func (_m *mockHead) IsValid() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsValid") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // newMockHead creates a new instance of mockHead. 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 newMockHead(t interface { diff --git a/common/client/mock_node_client_test.go b/common/client/mock_node_client_test.go index d143ebb88a5..dfe9f32664a 100644 --- a/common/client/mock_node_client_test.go +++ b/common/client/mock_node_client_test.go @@ -144,6 +144,34 @@ func (_m *mockNodeClient[CHAIN_ID, HEAD]) IsSyncing(ctx context.Context) (bool, return r0, r1 } +// LatestFinalizedBlock provides a mock function with given fields: ctx +func (_m *mockNodeClient[CHAIN_ID, HEAD]) LatestFinalizedBlock(ctx context.Context) (HEAD, error) { + ret := _m.Called(ctx) + + if len(ret) == 0 { + panic("no return value specified for LatestFinalizedBlock") + } + + var r0 HEAD + var r1 error + if rf, ok := ret.Get(0).(func(context.Context) (HEAD, error)); ok { + return rf(ctx) + } + if rf, ok := ret.Get(0).(func(context.Context) HEAD); ok { + r0 = rf(ctx) + } else { + r0 = ret.Get(0).(HEAD) + } + + if rf, ok := ret.Get(1).(func(context.Context) error); ok { + r1 = rf(ctx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // SetAliveLoopSub provides a mock function with given fields: _a0 func (_m *mockNodeClient[CHAIN_ID, HEAD]) SetAliveLoopSub(_a0 types.Subscription) { _m.Called(_a0) diff --git a/common/client/mocks/config.go b/common/client/mocks/config.go new file mode 100644 index 00000000000..27b717f61a0 --- /dev/null +++ b/common/client/mocks/config.go @@ -0,0 +1,30 @@ +package mocks + +import ( + "time" + + commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" +) + +type ChainConfig struct { + IsFinalityTagEnabled bool + FinalityDepthVal uint32 + NoNewHeadsThresholdVal time.Duration + ChainTypeVal commonconfig.ChainType +} + +func (t ChainConfig) ChainType() commonconfig.ChainType { + return t.ChainTypeVal +} + +func (t ChainConfig) NodeNoNewHeadsThreshold() time.Duration { + return t.NoNewHeadsThresholdVal +} + +func (t ChainConfig) FinalityDepth() uint32 { + return t.FinalityDepthVal +} + +func (t ChainConfig) FinalityTagEnabled() bool { + return t.IsFinalityTagEnabled +} diff --git a/common/client/models.go b/common/client/models.go index d0cf42a3844..66f1e9cf88b 100644 --- a/common/client/models.go +++ b/common/client/models.go @@ -18,6 +18,7 @@ const ( InsufficientFunds // Tx was rejected due to insufficient funds. ExceedsMaxFee // Attempt's fee was higher than the node's limit and got rejected. FeeOutOfValidRange // This error is returned when we use a fee price suggested from an RPC, but the network rejects the attempt due to an invalid range(mostly used by L2 chains). Retry by requesting a new suggested fee price. + OutOfCounters // The error returned when a transaction is too complex to be proven by zk circuits. This error is mainly returned by zk chains. sendTxReturnCodeLen // tracks the number of errors. Must always be last ) diff --git a/common/client/multi_node_test.go b/common/client/multi_node_test.go index 43e4127556a..9c09bd57d70 100644 --- a/common/client/multi_node_test.go +++ b/common/client/multi_node_test.go @@ -848,6 +848,14 @@ func TestMultiNode_SendTransaction_aggregateTxResults(t *testing.T) { ExpectedCriticalErr: "expected at least one response on SendTransaction", ResultsByCode: map[SendTxReturnCode][]error{}, }, + { + Name: "Zk out of counter error", + ExpectedTxResult: "not enough keccak counters to continue the execution", + ExpectedCriticalErr: "", + ResultsByCode: map[SendTxReturnCode][]error{ + OutOfCounters: {errors.New("not enough keccak counters to continue the execution")}, + }, + }, } for _, testCase := range testCases { diff --git a/common/client/node.go b/common/client/node.go index 082b1b45f99..61816be21da 100644 --- a/common/client/node.go +++ b/common/client/node.go @@ -15,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" + commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/common/types" ) @@ -43,6 +44,14 @@ type NodeConfig interface { SelectionMode() string SyncThreshold() uint32 NodeIsSyncingEnabled() bool + FinalizedBlockPollInterval() time.Duration +} + +type ChainConfig interface { + NodeNoNewHeadsThreshold() time.Duration + FinalityDepth() uint32 + FinalityTagEnabled() bool + ChainType() commonconfig.ChainType } //go:generate mockery --quiet --name Node --structname mockNode --filename "mock_node_test.go" --inpackage --case=underscore @@ -73,14 +82,14 @@ type node[ RPC NodeClient[CHAIN_ID, HEAD], ] struct { services.StateMachine - lfcLog logger.Logger - name string - id int32 - chainID CHAIN_ID - nodePoolCfg NodeConfig - noNewHeadsThreshold time.Duration - order int32 - chainFamily string + lfcLog logger.Logger + name string + id int32 + chainID CHAIN_ID + nodePoolCfg NodeConfig + chainCfg ChainConfig + order int32 + chainFamily string ws url.URL http *url.URL @@ -90,8 +99,9 @@ type node[ stateMu sync.RWMutex // protects state* fields state nodeState // Each node is tracking the last received head number and total difficulty - stateLatestBlockNumber int64 - stateLatestTotalDifficulty *big.Int + stateLatestBlockNumber int64 + stateLatestTotalDifficulty *big.Int + stateLatestFinalizedBlockNumber int64 // nodeCtx is the node lifetime's context nodeCtx context.Context @@ -113,7 +123,7 @@ func NewNode[ RPC NodeClient[CHAIN_ID, HEAD], ]( nodeCfg NodeConfig, - noNewHeadsThreshold time.Duration, + chainCfg ChainConfig, lggr logger.Logger, wsuri url.URL, httpuri *url.URL, @@ -129,7 +139,7 @@ func NewNode[ n.id = id n.chainID = chainID n.nodePoolCfg = nodeCfg - n.noNewHeadsThreshold = noNewHeadsThreshold + n.chainCfg = chainCfg n.ws = wsuri n.order = nodeOrder if httpuri != nil { diff --git a/common/client/node_lifecycle.go b/common/client/node_lifecycle.go index 20902277480..4707a60426f 100644 --- a/common/client/node_lifecycle.go +++ b/common/client/node_lifecycle.go @@ -22,6 +22,10 @@ var ( Name: "pool_rpc_node_highest_seen_block", Help: "The highest seen block for the given RPC node", }, []string{"chainID", "nodeName"}) + promPoolRPCNodeHighestFinalizedBlock = promauto.NewGaugeVec(prometheus.GaugeOpts{ + Name: "pool_rpc_node_highest_finalized_block", + Help: "The highest seen finalized block for the given RPC node", + }, []string{"chainID", "nodeName"}) promPoolRPCNodeNumSeenBlocks = promauto.NewCounterVec(prometheus.CounterOpts{ Name: "pool_rpc_node_num_seen_blocks", Help: "The total number of new blocks seen by the given RPC node", @@ -88,7 +92,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { } } - noNewHeadsTimeoutThreshold := n.noNewHeadsThreshold + noNewHeadsTimeoutThreshold := n.chainCfg.NodeNoNewHeadsThreshold() pollFailureThreshold := n.nodePoolCfg.PollFailureThreshold() pollInterval := n.nodePoolCfg.PollInterval() @@ -134,6 +138,14 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { lggr.Debug("Polling disabled") } + var pollFinalizedHeadCh <-chan time.Time + if n.chainCfg.FinalityTagEnabled() && n.nodePoolCfg.FinalizedBlockPollInterval() > 0 { + lggr.Debugw("Finalized block polling enabled") + pollT := time.NewTicker(n.nodePoolCfg.FinalizedBlockPollInterval()) + defer pollT.Stop() + pollFinalizedHeadCh = pollT.C + } + _, highestReceivedBlockNumber, _ := n.StateAndLatest() var pollFailures uint32 @@ -201,6 +213,13 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { outOfSyncT.Reset(noNewHeadsTimeoutThreshold) } n.setLatestReceived(bh.BlockNumber(), bh.BlockDifficulty()) + if !n.chainCfg.FinalityTagEnabled() { + latestFinalizedBN := max(bh.BlockNumber()-int64(n.chainCfg.FinalityDepth()), 0) + if latestFinalizedBN > n.stateLatestFinalizedBlockNumber { + promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) + n.stateLatestFinalizedBlockNumber = latestFinalizedBN + } + } case err := <-sub.Err(): lggr.Errorw("Subscription was terminated", "err", err, "nodeState", n.State()) n.declareUnreachable() @@ -214,13 +233,33 @@ func (n *node[CHAIN_ID, HEAD, RPC]) aliveLoop() { lggr.Criticalf("RPC endpoint detected out of sync; %s %s", msgCannotDisable, msgDegradedState) // We don't necessarily want to wait the full timeout to check again, we should // check regularly and log noisily in this state - outOfSyncT.Reset(zombieNodeCheckInterval(n.noNewHeadsThreshold)) + outOfSyncT.Reset(zombieNodeCheckInterval(noNewHeadsTimeoutThreshold)) continue } } n.declareOutOfSync(func(num int64, td *big.Int) bool { return num < highestReceivedBlockNumber }) return + case <-pollFinalizedHeadCh: + ctx, cancel := context.WithTimeout(n.nodeCtx, n.nodePoolCfg.FinalizedBlockPollInterval()) + latestFinalized, err := n.RPC().LatestFinalizedBlock(ctx) + cancel() + if err != nil { + lggr.Warnw("Failed to fetch latest finalized block", "err", err) + continue + } + + if !latestFinalized.IsValid() { + lggr.Warn("Latest finalized block is not valid") + continue + } + + latestFinalizedBN := latestFinalized.BlockNumber() + if latestFinalizedBN > n.stateLatestFinalizedBlockNumber { + promPoolRPCNodeHighestFinalizedBlock.WithLabelValues(n.chainID.String(), n.name).Set(float64(latestFinalizedBN)) + n.stateLatestFinalizedBlockNumber = latestFinalizedBN + } } + } } @@ -316,7 +355,7 @@ func (n *node[CHAIN_ID, HEAD, RPC]) outOfSyncLoop(isOutOfSync func(num int64, td return } lggr.Debugw(msgReceivedBlock, "blockNumber", head.BlockNumber(), "blockDifficulty", head.BlockDifficulty(), "nodeState", n.State()) - case <-time.After(zombieNodeCheckInterval(n.noNewHeadsThreshold)): + case <-time.After(zombieNodeCheckInterval(n.chainCfg.NodeNoNewHeadsThreshold())): if n.nLiveNodes != nil { if l, _, _ := n.nLiveNodes(); l < 1 { lggr.Critical("RPC endpoint is still out of sync, but there are no other available nodes. This RPC node will be forcibly moved back into the live pool in a degraded state") diff --git a/common/client/node_lifecycle_test.go b/common/client/node_lifecycle_test.go index 437bc4a655b..b3c09b35000 100644 --- a/common/client/node_lifecycle_test.go +++ b/common/client/node_lifecycle_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/cometbft/cometbft/libs/rand" + prom "github.com/prometheus/client_model/go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" @@ -17,6 +18,7 @@ import ( bigmath "github.com/smartcontractkit/chainlink-common/pkg/utils/big_math" "github.com/smartcontractkit/chainlink-common/pkg/utils/tests" + clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" "github.com/smartcontractkit/chainlink/v2/common/types" "github.com/smartcontractkit/chainlink/v2/common/types/mocks" ) @@ -283,9 +285,11 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { t.Parallel() rpc := newMockNodeClient[types.ID, Head](t) node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - noNewHeadsThreshold: tests.TestInterval, - rpc: rpc, + config: testNodeConfig{}, + chainConfig: clientMocks.ChainConfig{ + NoNewHeadsThresholdVal: tests.TestInterval, + }, + rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() // tries to redial in outOfSync @@ -308,10 +312,12 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc := newMockNodeClient[types.ID, Head](t) lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newSubscribedNode(t, testNodeOpts{ - config: testNodeConfig{}, - lggr: lggr, - noNewHeadsThreshold: tests.TestInterval, - rpc: rpc, + config: testNodeConfig{}, + lggr: lggr, + chainConfig: clientMocks.ChainConfig{ + NoNewHeadsThresholdVal: tests.TestInterval, + }, + rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { @@ -335,10 +341,12 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { rpc.On("SetAliveLoopSub", sub).Once() lggr, observedLogs := logger.TestObserved(t, zap.ErrorLevel) node := newDialedNode(t, testNodeOpts{ - lggr: lggr, - config: testNodeConfig{}, - noNewHeadsThreshold: tests.TestInterval, - rpc: rpc, + lggr: lggr, + config: testNodeConfig{}, + chainConfig: clientMocks.ChainConfig{ + NoNewHeadsThresholdVal: tests.TestInterval, + }, + rpc: rpc, }) defer func() { assert.NoError(t, node.close()) }() // disconnects all on transfer to unreachable or outOfSync @@ -374,6 +382,128 @@ func TestUnit_NodeLifecycle_aliveLoop(t *testing.T) { return state == nodeStateAlive && block == expectedBlockNumber == bigmath.Equal(diff, expectedDiff) }) }) + t.Run("If finality tag is not enabled updates finalized block metric using finality depth and latest head", func(t *testing.T) { + t.Parallel() + rpc := newMockNodeClient[types.ID, Head](t) + sub := mocks.NewSubscription(t) + sub.On("Err").Return((<-chan error)(nil)) + sub.On("Unsubscribe").Once() + const blockNumber = 1000 + const finalityDepth = 10 + const expectedBlock = 990 + rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + ch := args.Get(1).(chan<- Head) + go writeHeads(t, ch, head{BlockNumber: blockNumber - 1}, head{BlockNumber: blockNumber}, head{BlockNumber: blockNumber - 1}) + }).Return(sub, nil).Once() + rpc.On("SetAliveLoopSub", sub).Once() + name := "node-" + rand.Str(5) + node := newDialedNode(t, testNodeOpts{ + config: testNodeConfig{}, + chainConfig: clientMocks.ChainConfig{FinalityDepthVal: finalityDepth}, + rpc: rpc, + name: name, + chainID: big.NewInt(1), + }) + defer func() { assert.NoError(t, node.close()) }() + node.declareAlive() + tests.AssertEventually(t, func() bool { + metric, err := promPoolRPCNodeHighestFinalizedBlock.GetMetricWithLabelValues(big.NewInt(1).String(), name) + require.NoError(t, err) + var m = &prom.Metric{} + require.NoError(t, metric.Write(m)) + return float64(expectedBlock) == m.Gauge.GetValue() + }) + }) + t.Run("Logs warning if failed to get finalized block", func(t *testing.T) { + t.Parallel() + rpc := newMockNodeClient[types.ID, Head](t) + rpc.On("LatestFinalizedBlock", mock.Anything).Return(newMockHead(t), errors.New("failed to get finalized block")) + sub := mocks.NewSubscription(t) + sub.On("Err").Return((<-chan error)(nil)) + sub.On("Unsubscribe").Once() + rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SetAliveLoopSub", sub).Once() + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + node := newDialedNode(t, testNodeOpts{ + config: testNodeConfig{ + finalizedBlockPollInterval: tests.TestInterval, + }, + chainConfig: clientMocks.ChainConfig{ + IsFinalityTagEnabled: true, + }, + rpc: rpc, + lggr: lggr, + }) + defer func() { assert.NoError(t, node.close()) }() + node.declareAlive() + tests.AssertLogEventually(t, observedLogs, "Failed to fetch latest finalized block") + }) + t.Run("Logs warning if latest finalized block is not valid", func(t *testing.T) { + t.Parallel() + rpc := newMockNodeClient[types.ID, Head](t) + head := newMockHead(t) + head.On("IsValid").Return(false) + rpc.On("LatestFinalizedBlock", mock.Anything).Return(head, nil) + sub := mocks.NewSubscription(t) + sub.On("Err").Return((<-chan error)(nil)) + sub.On("Unsubscribe").Once() + rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Return(sub, nil).Once() + rpc.On("SetAliveLoopSub", sub).Once() + lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) + node := newDialedNode(t, testNodeOpts{ + config: testNodeConfig{ + finalizedBlockPollInterval: tests.TestInterval, + }, + chainConfig: clientMocks.ChainConfig{ + IsFinalityTagEnabled: true, + }, + rpc: rpc, + lggr: lggr, + }) + defer func() { assert.NoError(t, node.close()) }() + node.declareAlive() + tests.AssertLogEventually(t, observedLogs, "Latest finalized block is not valid") + }) + t.Run("If finality tag and finalized block polling are enabled updates latest finalized block metric", func(t *testing.T) { + t.Parallel() + rpc := newMockNodeClient[types.ID, Head](t) + const expectedBlock = 1101 + const finalityDepth = 10 + rpc.On("LatestFinalizedBlock", mock.Anything).Return(head{BlockNumber: expectedBlock - 1}.ToMockHead(t), nil).Once() + rpc.On("LatestFinalizedBlock", mock.Anything).Return(head{BlockNumber: expectedBlock}.ToMockHead(t), nil) + sub := mocks.NewSubscription(t) + sub.On("Err").Return((<-chan error)(nil)) + sub.On("Unsubscribe").Once() + rpc.On("Subscribe", mock.Anything, mock.Anything, rpcSubscriptionMethodNewHeads).Run(func(args mock.Arguments) { + ch := args.Get(1).(chan<- Head) + // ensure that "calculated" finalized head is larger than actual, to ensure we are correctly setting + // the metric + go writeHeads(t, ch, head{BlockNumber: expectedBlock*2 + finalityDepth}) + }).Return(sub, nil).Once() + rpc.On("SetAliveLoopSub", sub).Once() + name := "node-" + rand.Str(5) + node := newDialedNode(t, testNodeOpts{ + config: testNodeConfig{ + finalizedBlockPollInterval: tests.TestInterval, + }, + chainConfig: clientMocks.ChainConfig{ + FinalityDepthVal: finalityDepth, + IsFinalityTagEnabled: true, + }, + rpc: rpc, + name: name, + chainID: big.NewInt(1), + }) + defer func() { assert.NoError(t, node.close()) }() + node.declareAlive() + tests.AssertEventually(t, func() bool { + metric, err := promPoolRPCNodeHighestFinalizedBlock.GetMetricWithLabelValues(big.NewInt(1).String(), name) + require.NoError(t, err) + var m = &prom.Metric{} + require.NoError(t, metric.Write(m)) + return float64(expectedBlock) == m.Gauge.GetValue() + }) + }) } type head struct { @@ -381,11 +511,17 @@ type head struct { BlockDifficulty *big.Int } +func (h head) ToMockHead(t *testing.T) *mockHead { + m := newMockHead(t) + m.On("BlockNumber").Return(h.BlockNumber).Maybe() + m.On("BlockDifficulty").Return(h.BlockDifficulty).Maybe() + m.On("IsValid").Return(true).Maybe() + return m +} + func writeHeads(t *testing.T, ch chan<- Head, heads ...head) { for _, head := range heads { - h := newMockHead(t) - h.On("BlockNumber").Return(head.BlockNumber) - h.On("BlockDifficulty").Return(head.BlockDifficulty) + h := head.ToMockHead(t) select { case ch <- h: case <-tests.Context(t).Done(): @@ -675,10 +811,12 @@ func TestUnit_NodeLifecycle_outOfSyncLoop(t *testing.T) { nodeChainID := types.RandomID() lggr, observedLogs := logger.TestObserved(t, zap.DebugLevel) node := newAliveNode(t, testNodeOpts{ - noNewHeadsThreshold: tests.TestInterval, - rpc: rpc, - chainID: nodeChainID, - lggr: lggr, + chainConfig: clientMocks.ChainConfig{ + NoNewHeadsThresholdVal: tests.TestInterval, + }, + rpc: rpc, + chainID: nodeChainID, + lggr: lggr, }) defer func() { assert.NoError(t, node.close()) }() node.nLiveNodes = func() (count int, blockNumber int64, totalDifficulty *big.Int) { @@ -1234,7 +1372,7 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { } for _, td := range []int64{totalDifficulty - syncThreshold - 1, totalDifficulty - syncThreshold, totalDifficulty, totalDifficulty + 1} { for _, testCase := range testCases { - t.Run(fmt.Sprintf("%s: selectionMode: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { + t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: total difficulty: %d", testCase.name, selectionMode, td), func(t *testing.T) { outOfSync, liveNodes := node.syncStatus(testCase.blockNumber, big.NewInt(td)) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) @@ -1287,7 +1425,7 @@ func TestUnit_NodeLifecycle_syncStatus(t *testing.T) { } for _, hb := range []int64{highestBlock - syncThreshold - 1, highestBlock - syncThreshold, highestBlock, highestBlock + 1} { for _, testCase := range testCases { - t.Run(fmt.Sprintf("%s: selectionMode: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { + t.Run(fmt.Sprintf("%s: SelectionModeVal: %s: highest block: %d", testCase.name, NodeSelectionModeTotalDifficulty, hb), func(t *testing.T) { outOfSync, liveNodes := node.syncStatus(hb, big.NewInt(testCase.totalDifficulty)) assert.Equal(t, nodesNum, liveNodes) assert.Equal(t, testCase.outOfSync, outOfSync) diff --git a/common/client/node_test.go b/common/client/node_test.go index c7a7a710d8f..a97f26555a9 100644 --- a/common/client/node_test.go +++ b/common/client/node_test.go @@ -7,15 +7,17 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" + clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" "github.com/smartcontractkit/chainlink/v2/common/types" ) type testNodeConfig struct { - pollFailureThreshold uint32 - pollInterval time.Duration - selectionMode string - syncThreshold uint32 - nodeIsSyncingEnabled bool + pollFailureThreshold uint32 + pollInterval time.Duration + selectionMode string + syncThreshold uint32 + nodeIsSyncingEnabled bool + finalizedBlockPollInterval time.Duration } func (n testNodeConfig) PollFailureThreshold() uint32 { @@ -38,22 +40,26 @@ func (n testNodeConfig) NodeIsSyncingEnabled() bool { return n.nodeIsSyncingEnabled } +func (n testNodeConfig) FinalizedBlockPollInterval() time.Duration { + return n.finalizedBlockPollInterval +} + type testNode struct { *node[types.ID, Head, NodeClient[types.ID, Head]] } type testNodeOpts struct { - config testNodeConfig - noNewHeadsThreshold time.Duration - lggr logger.Logger - wsuri url.URL - httpuri *url.URL - name string - id int32 - chainID types.ID - nodeOrder int32 - rpc *mockNodeClient[types.ID, Head] - chainFamily string + config testNodeConfig + chainConfig clientMocks.ChainConfig + lggr logger.Logger + wsuri url.URL + httpuri *url.URL + name string + id int32 + chainID types.ID + nodeOrder int32 + rpc *mockNodeClient[types.ID, Head] + chainFamily string } func newTestNode(t *testing.T, opts testNodeOpts) testNode { @@ -77,7 +83,7 @@ func newTestNode(t *testing.T, opts testNodeOpts) testNode { opts.id = 42 } - nodeI := NewNode[types.ID, Head, NodeClient[types.ID, Head]](opts.config, opts.noNewHeadsThreshold, opts.lggr, + nodeI := NewNode[types.ID, Head, NodeClient[types.ID, Head]](opts.config, opts.chainConfig, opts.lggr, opts.wsuri, opts.httpuri, opts.name, opts.id, opts.chainID, opts.nodeOrder, opts.rpc, opts.chainFamily) return testNode{ diff --git a/common/client/types.go b/common/client/types.go index 8d7b5b71b83..a27e6a50b73 100644 --- a/common/client/types.go +++ b/common/client/types.go @@ -53,6 +53,7 @@ type RPC[ type Head interface { BlockNumber() int64 BlockDifficulty() *big.Int + IsValid() bool } // NodeClient includes all the necessary RPC methods required by a node. @@ -72,6 +73,7 @@ type NodeClient[ SetAliveLoopSub(types.Subscription) UnsubscribeAllExceptAliveLoop() IsSyncing(ctx context.Context) (bool, error) + LatestFinalizedBlock(ctx context.Context) (HEAD, error) } // clientAPI includes all the direct RPC methods required by the generalized common client to implement its own. diff --git a/common/types/head.go b/common/types/head.go index c363fd5d0f2..4ecdb981c78 100644 --- a/common/types/head.go +++ b/common/types/head.go @@ -36,4 +36,6 @@ type Head[BLOCK_HASH Hashable] interface { // Returns the total difficulty of the block. For chains who do not have a concept of block // difficulty, return 0. BlockDifficulty() *big.Int + // IsValid returns true if the head is valid. + IsValid() bool } diff --git a/common/types/mocks/head.go b/common/types/mocks/head.go index 29b6d073656..fd5c95d472f 100644 --- a/common/types/mocks/head.go +++ b/common/types/mocks/head.go @@ -184,6 +184,24 @@ func (_m *Head[BLOCK_HASH]) HashAtHeight(blockNum int64) BLOCK_HASH { return r0 } +// IsValid provides a mock function with given fields: +func (_m *Head[BLOCK_HASH]) IsValid() bool { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for IsValid") + } + + var r0 bool + if rf, ok := ret.Get(0).(func() bool); ok { + r0 = rf() + } else { + r0 = ret.Get(0).(bool) + } + + return r0 +} + // NewHead creates a new instance of Head. 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 NewHead[BLOCK_HASH types.Hashable](t interface { diff --git a/contracts/.changeset/afraid-years-fix.md b/contracts/.changeset/afraid-years-fix.md new file mode 100644 index 00000000000..7048f562312 --- /dev/null +++ b/contracts/.changeset/afraid-years-fix.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +upgraded transmission to 0.8.19 diff --git a/contracts/.changeset/early-hairs-wonder.md b/contracts/.changeset/early-hairs-wonder.md new file mode 100644 index 00000000000..808c89f8451 --- /dev/null +++ b/contracts/.changeset/early-hairs-wonder.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +fix bug in auto2.3 withdrawERC20Fees diff --git a/contracts/.changeset/eight-peas-glow.md b/contracts/.changeset/eight-peas-glow.md new file mode 100644 index 00000000000..03c0498abe2 --- /dev/null +++ b/contracts/.changeset/eight-peas-glow.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": minor +--- + +VRFV2PlusWrapper config refactor diff --git a/contracts/.changeset/famous-feet-rescue.md b/contracts/.changeset/famous-feet-rescue.md new file mode 100644 index 00000000000..d955046ceb9 --- /dev/null +++ b/contracts/.changeset/famous-feet-rescue.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +fix withdraw LINK bug in auto 2.3 diff --git a/contracts/.changeset/loud-donuts-work.md b/contracts/.changeset/loud-donuts-work.md new file mode 100644 index 00000000000..e177af6fb3e --- /dev/null +++ b/contracts/.changeset/loud-donuts-work.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +rm hh coverage diff --git a/contracts/.changeset/lucky-bananas-kneel.md b/contracts/.changeset/lucky-bananas-kneel.md new file mode 100644 index 00000000000..2c2b8d5b321 --- /dev/null +++ b/contracts/.changeset/lucky-bananas-kneel.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +mv vrf foundry tests diff --git a/contracts/.changeset/nine-comics-bathe.md b/contracts/.changeset/nine-comics-bathe.md new file mode 100644 index 00000000000..7d8573cd784 --- /dev/null +++ b/contracts/.changeset/nine-comics-bathe.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": minor +--- + +Removed 0.6 and 0.7 Solidity source code diff --git a/contracts/.changeset/six-donuts-reply.md b/contracts/.changeset/six-donuts-reply.md new file mode 100644 index 00000000000..a9da93964be --- /dev/null +++ b/contracts/.changeset/six-donuts-reply.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +small gas fix diff --git a/contracts/.changeset/strange-actors-do.md b/contracts/.changeset/strange-actors-do.md new file mode 100644 index 00000000000..644e30f2a09 --- /dev/null +++ b/contracts/.changeset/strange-actors-do.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +Set LINK native feed in VRFV2PlusWrapper to immutable diff --git a/contracts/.changeset/tasty-rings-bow.md b/contracts/.changeset/tasty-rings-bow.md new file mode 100644 index 00000000000..828050c6eeb --- /dev/null +++ b/contracts/.changeset/tasty-rings-bow.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": patch +--- + +add billing override test diff --git a/contracts/.changeset/tricky-pigs-shout.md b/contracts/.changeset/tricky-pigs-shout.md new file mode 100644 index 00000000000..095fc06701c --- /dev/null +++ b/contracts/.changeset/tricky-pigs-shout.md @@ -0,0 +1,5 @@ +--- +"@chainlink/contracts": minor +--- + +bug fixes in s_reserveAmount accounting diff --git a/contracts/.prettierignore b/contracts/.prettierignore index 66ef5e3fcde..b2c6d61c220 100644 --- a/contracts/.prettierignore +++ b/contracts/.prettierignore @@ -21,8 +21,6 @@ node_modules solc LinkToken.json typechain -src/v0.6 -src/v0.7 **/vendor # Ignore TS definition and map files diff --git a/contracts/.solcover.js b/contracts/.solcover.js deleted file mode 100644 index d49e118e4a8..00000000000 --- a/contracts/.solcover.js +++ /dev/null @@ -1,29 +0,0 @@ -module.exports = { - skipFiles: [ - 'v0.6/', - 'v0.7/', - 'v0.8/mocks', - 'v0.8/interfaces', - 'v0.8/vendor', - 'v0.8/dev/interfaces', - 'v0.8/dev/vendor', - 'v0.8/dev/Keeper2_0/interfaces', - 'v0.8/dev/transmission', - 'v0.8/tests', - ], - istanbulReporter: ['text', 'text-summary', 'json'], - mocha: { - grep: '@skip-coverage', // Find everything with this tag - invert: true, // Run the grep's inverse set. - }, - configureYulOptimizer: true, - solcOptimizerDetails: { - peephole: false, - jumpdestRemover: false, - orderLiterals: true, - deduplicate: false, - cse: false, - constantOptimizer: false, - yul: true, - }, -} diff --git a/contracts/GNUmakefile b/contracts/GNUmakefile index 751a47b3be4..7550e645ff2 100644 --- a/contracts/GNUmakefile +++ b/contracts/GNUmakefile @@ -1,6 +1,6 @@ # ALL_FOUNDRY_PRODUCTS contains a list of all products that have a foundry # profile defined and use the Foundry snapshots. -ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions keystone shared +ALL_FOUNDRY_PRODUCTS = l2ep llo-feeds functions keystone shared transmission # To make a snapshot for a specific product, either set the `FOUNDRY_PROFILE` env var # or call the target with `FOUNDRY_PROFILE=product` diff --git a/contracts/README.md b/contracts/README.md index aa4a230405b..528e331331d 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -14,12 +14,8 @@ $ npm install @chainlink/contracts --save ```sh @chainlink/contracts ├── src # Solidity contracts -│ ├── v0.6 -│ ├── v0.7 │ └── v0.8 └── abi # ABI json output - ├── v0.6 - ├── v0.7 └── v0.8 ``` diff --git a/contracts/foundry.toml b/contracts/foundry.toml index 6563c394223..bbc9f395942 100644 --- a/contracts/foundry.toml +++ b/contracts/foundry.toml @@ -4,7 +4,7 @@ optimizer = true optimizer_runs = 1_000_000 src = 'src/v0.8' -test = 'test/v0.8/foundry' +test = 'test/v0.8' out = 'foundry-artifacts' cache_path = 'foundry-cache' libs = ['node_modules', 'foundry-lib'] @@ -23,9 +23,9 @@ test = 'src/v0.8/functions/tests/v1_X' gas_price = 3_000_000_000 # 3 gwei [profile.vrf] -optimizer_runs = 1000 +optimizer_runs = 1_000 src = 'src/v0.8/vrf' -test = 'test/v0.8/foundry/vrf' # skips tests for no VRF foundry tests +test = 'src/v0.8/vrf/test' [profile.vrfv2plus_coordinator] optimizer_runs = 500 @@ -36,22 +36,21 @@ optimizer_runs = 1_000_000 src = 'src/v0.8/vrf' [profile.automation] -optimizer_runs = 10000 +optimizer_runs = 10_000 src = 'src/v0.8/automation' test = 'src/v0.8/automation/test' [profile.l2ep] -optimizer_runs = 1000000 +optimizer_runs = 1_000_000 src = 'src/v0.8/l2ep' test = 'src/v0.8/l2ep/test' solc_version = '0.8.19' [profile.llo-feeds] -optimizer_runs = 1000000 +optimizer_runs = 1_000_000 src = 'src/v0.8/llo-feeds' test = 'src/v0.8/llo-feeds/test' solc_version = '0.8.19' -# We cannot turn on deny_warnings = true as that will hide any CI failure [profile.keystone] solc_version = '0.8.19' @@ -59,8 +58,20 @@ src = 'src/v0.8/keystone' test = 'src/v0.8/keystone/test' optimizer_runs = 10_000 +[profile.operatorforwarder] +optimizer_runs = 1_000_000 +solc_version = '0.8.19' +src = 'src/v0.8/operatorforwarder' +test = 'src/v0.8/operatorforwarder/test' + +[profile.transmission] +optimizer_runs = 1_000_000 +solc_version = '0.8.19' +src = 'src/v0.8/transmission' +test = 'src/v0.8/transmission/test' + [profile.shared] -optimizer_runs = 1000000 +optimizer_runs = 1_000_000 src = 'src/v0.8/shared' test = 'src/v0.8/shared/test' solc_version = '0.8.19' diff --git a/contracts/gas-snapshots/transmission.gas-snapshot b/contracts/gas-snapshots/transmission.gas-snapshot new file mode 100644 index 00000000000..d0f5e3c14d2 --- /dev/null +++ b/contracts/gas-snapshots/transmission.gas-snapshot @@ -0,0 +1,4 @@ +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccount() (gas: 910039) +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymaster() (gas: 2286631) +EIP_712_1014_4337:testEIP712EIP4337AndCreateSmartContractAccountWithPaymasterForVRFRequest() (gas: 2876825) +EIP_712_1014_4337:testEIP712EIP4337WithExistingSmartContractAccount() (gas: 878457) \ No newline at end of file diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts index 4a2077041ad..8de0778c6cb 100644 --- a/contracts/hardhat.config.ts +++ b/contracts/hardhat.config.ts @@ -6,7 +6,6 @@ import '@typechain/hardhat' import 'hardhat-abi-exporter' import 'hardhat-contract-sizer' import 'hardhat-gas-reporter' -import 'solidity-coverage' import 'hardhat-ignore-warnings' import { subtask } from 'hardhat/config' import { TASK_COMPILE_SOLIDITY_GET_SOURCE_PATHS } from 'hardhat/builtin-tasks/task-names' @@ -60,22 +59,10 @@ let config = { }, solidity: { compilers: [ - { - version: '0.6.6', - settings: COMPILER_SETTINGS, - }, - { - version: '0.7.6', - settings: COMPILER_SETTINGS, - }, { version: '0.8.6', settings: COMPILER_SETTINGS, }, - { - version: '0.8.15', - settings: COMPILER_SETTINGS, - }, { version: '0.8.16', settings: COMPILER_SETTINGS, diff --git a/contracts/package.json b/contracts/package.json index 150b23f05d0..6973a6fd77d 100644 --- a/contracts/package.json +++ b/contracts/package.json @@ -67,7 +67,6 @@ "hardhat-contract-sizer": "^2.10.0", "hardhat-gas-reporter": "^1.0.9", "hardhat-ignore-warnings": "^0.2.6", - "istanbul": "^0.4.5", "moment": "^2.29.4", "prettier": "^3.2.5", "prettier-plugin-solidity": "1.3.1", @@ -75,7 +74,6 @@ "solhint": "^4.5.2", "solhint-plugin-chainlink-solidity": "git+https://github.com/smartcontractkit/chainlink-solhint-rules.git#v1.2.1", "solhint-plugin-prettier": "^0.1.0", - "solidity-coverage": "^0.8.5", "ts-node": "^10.9.2", "typechain": "^8.2.1", "typescript": "^5.4.3" diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml index 94e9a9a339d..c5e9e1f1410 100644 --- a/contracts/pnpm-lock.yaml +++ b/contracts/pnpm-lock.yaml @@ -136,9 +136,6 @@ devDependencies: hardhat-ignore-warnings: specifier: ^0.2.6 version: 0.2.9 - istanbul: - specifier: ^0.4.5 - version: 0.4.5 moment: specifier: ^2.29.4 version: 2.29.4 @@ -160,9 +157,6 @@ devDependencies: solhint-plugin-prettier: specifier: ^0.1.0 version: 0.1.0(prettier-plugin-solidity@1.3.1)(prettier@3.2.5) - solidity-coverage: - specifier: ^0.8.5 - version: 0.8.5(hardhat@2.19.2) ts-node: specifier: ^10.9.2 version: 10.9.2(@types/node@16.18.89)(typescript@5.4.3) @@ -1634,12 +1628,6 @@ packages: antlr4ts: 0.5.0-alpha.4 dev: true - /@solidity-parser/parser@0.16.0: - resolution: {integrity: sha512-ESipEcHyRHg4Np4SqBCfcXwyxxna1DgFVz69bgpLV8vzl/NP1DtcKsJ4dJZXWQhY/Z4J2LeKBiOkOVZn9ct33Q==} - dependencies: - antlr4ts: 0.5.0-alpha.4 - dev: true - /@solidity-parser/parser@0.17.0: resolution: {integrity: sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw==} dev: true @@ -1793,24 +1781,12 @@ packages: resolution: {integrity: sha512-jT0O3hAILDKeKbdWJ9FZLD0Xdfhz7hMvfyFlRWpirjiEVr8G+GZ4kVIzPIqM6x6Rpp93TNPgOAed4XmvcuV6Qg==} dev: true - /@types/events@3.0.0: - resolution: {integrity: sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==} - dev: true - /@types/form-data@0.0.33: resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} dependencies: '@types/node': 16.18.89 dev: true - /@types/glob@7.1.1: - resolution: {integrity: sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==} - dependencies: - '@types/events': 3.0.0 - '@types/minimatch': 3.0.3 - '@types/node': 16.18.89 - dev: true - /@types/http-cache-semantics@4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true @@ -1835,10 +1811,6 @@ packages: resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} dev: true - /@types/minimatch@3.0.3: - resolution: {integrity: sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==} - dev: true - /@types/minimist@1.2.5: resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==} dev: false @@ -2082,14 +2054,6 @@ packages: resolution: {integrity: sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==} dev: true - /abbrev@1.0.9: - resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - dev: true - - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true - /abi-to-sol@0.6.6: resolution: {integrity: sha512-PRn81rSpv6NXFPYQSw7ujruqIP6UkwZ/XoFldtiqCX8+2kHVc73xVaUVvdbro06vvBVZiwnxhEIGdI4BRMwGHw==} hasBin: true @@ -2176,11 +2140,6 @@ packages: hasBin: true dev: true - /address@1.1.2: - resolution: {integrity: sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==} - engines: {node: '>= 0.12.0'} - dev: true - /adm-zip@0.4.16: resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} engines: {node: '>=0.3.0'} @@ -2242,13 +2201,6 @@ packages: - encoding dev: true - /amdefine@1.0.1: - resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} - engines: {node: '>=0.4.2'} - requiresBuild: true - dev: true - optional: true - /ansi-colors@3.2.3: resolution: {integrity: sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==} engines: {node: '>=6'} @@ -4230,10 +4182,6 @@ packages: resolution: {integrity: sha512-68s5jYdlvasItOJnCuI2Q9s4q98g0pCyL3HrcKJu8KNugUl8ahgmZYg38ysLTgQjjXX3H8CJLkAvWrclWfcalw==} dev: false - /death@1.1.0: - resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} - dev: true - /debug@2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} peerDependencies: @@ -4488,17 +4436,6 @@ packages: engines: {node: '>=8'} dev: false - /detect-port@1.3.0: - resolution: {integrity: sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ==} - engines: {node: '>= 4.2.1'} - hasBin: true - dependencies: - address: 1.1.2 - debug: 2.6.9 - transitivePeerDependencies: - - supports-color - dev: true - /diff@3.5.0: resolution: {integrity: sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==} engines: {node: '>=0.3.1'} @@ -4524,12 +4461,6 @@ packages: dev: true optional: true - /difflib@0.2.4: - resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} - dependencies: - heap: 0.2.6 - dev: true - /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -4811,19 +4742,6 @@ packages: engines: {node: '>=10'} dev: true - /escodegen@1.8.1: - resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} - engines: {node: '>=0.12.0'} - hasBin: true - dependencies: - esprima: 2.7.3 - estraverse: 1.9.3 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.2.0 - dev: true - /eslint-config-prettier@9.1.0(eslint@8.57.0): resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} hasBin: true @@ -4923,12 +4841,6 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /esprima@2.7.3: - resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} - engines: {node: '>=0.10.0'} - hasBin: true - dev: true - /esprima@4.0.1: resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} engines: {node: '>=4'} @@ -4948,11 +4860,6 @@ packages: estraverse: 5.3.0 dev: true - /estraverse@1.9.3: - resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} - engines: {node: '>=0.10.0'} - dev: true - /estraverse@5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} @@ -5897,6 +5804,7 @@ packages: graceful-fs: 4.2.10 jsonfile: 4.0.0 universalify: 0.1.2 + dev: false /fs-extra@9.1.0: resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} @@ -6094,14 +6002,6 @@ packages: assert-plus: 1.0.0 dev: true - /ghost-testrpc@0.0.2: - resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} - hasBin: true - dependencies: - chalk: 2.4.2 - node-emoji: 1.11.0 - dev: true - /glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -6115,16 +6015,6 @@ packages: is-glob: 4.0.3 dev: true - /glob@5.0.15: - resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} - dependencies: - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - /glob@7.1.3: resolution: {integrity: sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==} dependencies: @@ -6180,22 +6070,6 @@ packages: once: 1.4.0 dev: true - /global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - dev: true - - /global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - dev: true - /global@4.3.2: resolution: {integrity: sha512-/4AybdwIDU4HkCUbJkZdWpe4P6vuw/CUtu+0I1YlLIPe7OlUO7KNJ+q/rO70CW2/NW6Jc6I62++Hzsf5Alu6rQ==} dependencies: @@ -6221,20 +6095,6 @@ packages: dependencies: define-properties: 1.2.1 - /globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - dependencies: - '@types/glob': 7.1.1 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.1 - glob: 7.2.3 - ignore: 5.2.4 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - /globby@11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} @@ -6330,19 +6190,6 @@ packages: engines: {node: '>=4.x'} dev: true - /handlebars@4.7.7: - resolution: {integrity: sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.6 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.17.3 - dev: true - /har-schema@2.0.0: resolution: {integrity: sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==} engines: {node: '>=4'} @@ -6483,11 +6330,6 @@ packages: /has-bigints@1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} - /has-flag@1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - dev: true - /has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -6816,11 +6658,6 @@ packages: hasown: 2.0.0 side-channel: 1.0.4 - /interpret@1.2.0: - resolution: {integrity: sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==} - engines: {node: '>= 0.10'} - dev: true - /invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} dependencies: @@ -7205,30 +7042,6 @@ packages: resolution: {integrity: sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==} dev: true - /istanbul@0.4.5: - resolution: {integrity: sha512-nMtdn4hvK0HjUlzr1DrKSUY8ychprt8dzHOgY2KXsIhHu5PuQQEOTM27gV9Xblyon7aUH/TSFIjRHEODF/FRPg==} - deprecated: |- - This module is no longer maintained, try this instead: - npm i nyc - Visit https://istanbul.js.org/integrations for other alternatives. - hasBin: true - dependencies: - abbrev: 1.0.9 - async: 1.5.2 - escodegen: 1.8.1 - esprima: 2.7.3 - glob: 5.0.15 - handlebars: 4.7.7 - js-yaml: 3.14.1 - mkdirp: 0.5.6 - nopt: 3.0.6 - once: 1.4.0 - resolve: 1.1.7 - supports-color: 3.2.3 - which: 1.3.1 - wordwrap: 1.0.0 - dev: true - /isurl@1.0.0: resolution: {integrity: sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==} engines: {node: '>= 4'} @@ -7279,6 +7092,7 @@ packages: dependencies: argparse: 1.0.10 esprima: 4.0.1 + dev: false /js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} @@ -7404,10 +7218,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /jsonschema@1.4.0: - resolution: {integrity: sha512-/YgW6pRMr6M7C+4o8kS+B/2myEpHCrxO4PEWnqJNBFMjn7EWXqlQ4tGwL6xTHeRplwuZmcAncdvfOad1nT2yMw==} - dev: true - /jsprim@1.4.1: resolution: {integrity: sha512-4Dj8Rf+fQ+/Pn7C5qeEX02op1WfOss3PKTE9Nsop3Dx+6UPxlm1dr/og7o2cRa5hNN07CACr4NFzRLtj/rjWog==} engines: {'0': node >=0.6.0} @@ -7655,14 +7465,6 @@ packages: engines: {node: '>=6'} dev: true - /levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: true - /levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -8394,10 +8196,6 @@ packages: dev: true optional: true - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - /neodoc@2.0.2: resolution: {integrity: sha512-NAppJ0YecKWdhSXFYCHbo6RutiX8vOt/Jo3l46mUg6pQlpJNaqc5cGxdrW2jITQm5JIYySbFVPDl3RrREXNyPw==} dependencies: @@ -8422,12 +8220,6 @@ packages: resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} dev: true - /node-emoji@1.11.0: - resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} - dependencies: - lodash: 4.17.21 - dev: true - /node-environment-flags@1.0.6: resolution: {integrity: sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==} dependencies: @@ -8475,13 +8267,6 @@ packages: engines: {node: '>=12.19'} dev: true - /nopt@3.0.6: - resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} - hasBin: true - dependencies: - abbrev: 1.1.1 - dev: true - /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: @@ -8638,18 +8423,6 @@ packages: is-wsl: 2.2.0 dev: true - /optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.3 - dev: true - /optionator@0.9.3: resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} engines: {node: '>= 0.8.0'} @@ -9009,6 +8782,7 @@ packages: /pify@4.0.1: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + dev: false /pinkie-promise@2.0.1: resolution: {integrity: sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==} @@ -9059,11 +8833,6 @@ packages: which-pm: 2.0.0 dev: false - /prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true - /prelude-ls@1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} @@ -9465,20 +9234,6 @@ packages: picomatch: 2.3.1 dev: true - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.1 - dev: true - - /recursive-readdir@2.2.2: - resolution: {integrity: sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==} - engines: {node: '>=0.10.0'} - dependencies: - minimatch: 3.0.4 - dev: true - /redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -9695,10 +9450,6 @@ packages: deprecated: https://github.com/lydell/resolve-url#deprecated dev: true - /resolve@1.1.7: - resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} - dev: true - /resolve@1.17.0: resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} dependencies: @@ -9833,26 +9584,6 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - /sc-istanbul@0.4.6: - resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} - hasBin: true - dependencies: - abbrev: 1.0.9 - async: 1.5.2 - escodegen: 1.8.1 - esprima: 2.7.3 - glob: 5.0.15 - handlebars: 4.7.7 - js-yaml: 3.14.1 - mkdirp: 0.5.6 - nopt: 3.0.6 - once: 1.4.0 - resolve: 1.1.7 - supports-color: 3.2.3 - which: 1.3.1 - wordwrap: 1.0.0 - dev: true - /scrypt-js@2.0.4: resolution: {integrity: sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==} dev: true @@ -10089,16 +9820,6 @@ packages: engines: {node: '>=8'} dev: true - /shelljs@0.8.3: - resolution: {integrity: sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==} - engines: {node: '>=4'} - hasBin: true - dependencies: - glob: 7.2.3 - interpret: 1.2.0 - rechoir: 0.6.2 - dev: true - /side-channel@1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: @@ -10397,37 +10118,6 @@ packages: solidity-comments-win32-x64-msvc: 0.0.2 dev: true - /solidity-coverage@0.8.5(hardhat@2.19.2): - resolution: {integrity: sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==} - hasBin: true - peerDependencies: - hardhat: ^2.11.0 - dependencies: - '@ethersproject/abi': 5.7.0 - '@solidity-parser/parser': 0.16.0 - chalk: 2.4.2 - death: 1.1.0 - detect-port: 1.3.0 - difflib: 0.2.4 - fs-extra: 8.1.0 - ghost-testrpc: 0.0.2 - global-modules: 2.0.0 - globby: 10.0.2 - hardhat: 2.19.2(ts-node@10.9.2)(typescript@5.4.3) - jsonschema: 1.4.0 - lodash: 4.17.21 - mocha: 10.2.0 - node-emoji: 1.11.0 - pify: 4.0.1 - recursive-readdir: 2.2.2 - sc-istanbul: 0.4.6 - semver: 7.5.4 - shelljs: 0.8.3 - web3-utils: 1.8.0 - transitivePeerDependencies: - - supports-color - dev: true - /sort-any@2.0.0: resolution: {integrity: sha512-T9JoiDewQEmWcnmPn/s9h/PH9t3d/LSWi0RgVmXSuDYeZXTZOZ1/wrK2PHaptuR1VXe3clLLt0pD6sgVOwjNEA==} dependencies: @@ -10470,15 +10160,6 @@ packages: deprecated: See https://github.com/lydell/source-map-url#deprecated dev: true - /source-map@0.2.0: - resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} - engines: {node: '>=0.8.0'} - requiresBuild: true - dependencies: - amdefine: 1.0.1 - dev: true - optional: true - /source-map@0.5.7: resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} engines: {node: '>=0.10.0'} @@ -10757,13 +10438,6 @@ packages: engines: {node: '>=0.8.0'} dev: true - /supports-color@3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} - dependencies: - has-flag: 1.0.0 - dev: true - /supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -11185,13 +10859,6 @@ packages: resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} dev: true - /type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: true - /type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} @@ -11366,14 +11033,6 @@ packages: engines: {node: '>=8'} dev: true - /uglify-js@3.17.3: - resolution: {integrity: sha512-JmMFDME3iufZnBpyKL+uS78LRiC+mK55zWfM5f/pWBJfpOttXAqYfdDGRukYhJuyRinvPVAtUhvy7rlDybNtFg==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - /ultron@1.1.1: resolution: {integrity: sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==} requiresBuild: true @@ -12069,15 +11728,6 @@ packages: hasBin: true dev: true - /word-wrap@1.2.3: - resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} - engines: {node: '>=0.10.0'} - dev: true - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - /wordwrapjs@4.0.1: resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} engines: {node: '>=8.0.0'} diff --git a/contracts/scripts/native_solc_compile_all b/contracts/scripts/native_solc_compile_all index f4cec6ce1ee..542337a191a 100755 --- a/contracts/scripts/native_solc_compile_all +++ b/contracts/scripts/native_solc_compile_all @@ -12,7 +12,7 @@ python3 -m pip install --require-hashes -r $SCRIPTPATH/requirements.txt # 6 and 7 are legacy contracts, for each other product we have a native_solc_compile_all_$product script # These scripts can be run individually, or all together with this script. # To add new CL products, simply write a native_solc_compile_all_$product script and add it to the list below. -for product in 6 7 automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared transmission vrf +for product in automation events_mock feeds functions keystone llo-feeds logpoller operatorforwarder shared transmission vrf do $SCRIPTPATH/native_solc_compile_all_$product done diff --git a/contracts/scripts/native_solc_compile_all_6 b/contracts/scripts/native_solc_compile_all_6 deleted file mode 100755 index f7bd60d6781..00000000000 --- a/contracts/scripts/native_solc_compile_all_6 +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo " ┌──────────────────────────────────────────────┐" -echo " │ Compiling legacy Solidity 0.6 contracts... │" -echo " └──────────────────────────────────────────────┘" - -SOLC_VERSION="0.6.6" -OPTIMIZE_RUNS=1000000 - - -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt - -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - - -compileContract () { - local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v0.6/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.6 \ - "$ROOT"/contracts/src/v0.6/"$1" -} - -compileContract Flags.sol -compileContract Oracle.sol -compileContract FluxAggregator.sol -compileContract VRF.sol -compileContract VRFCoordinator.sol -compileContract tests/VRFRequestIDBaseTestHelper.sol -compileContract tests/VRFTestHelper.sol -compileContract Chainlink.sol -compileContract VRFRequestIDBase.sol -compileContract tests/VRFConsumer.sol -compileContract ChainlinkClient.sol -compileContract VRFConsumerBase.sol -compileContract BlockhashStore.sol -compileContract tests/TestAPIConsumer.sol -compileContract tests/MockETHLINKAggregator.sol -compileContract tests/MockGASAggregator.sol \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_7 b/contracts/scripts/native_solc_compile_all_7 deleted file mode 100755 index fd64d9ffce7..00000000000 --- a/contracts/scripts/native_solc_compile_all_7 +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo " ┌──────────────────────────────────────────────┐" -echo " │ Compiling legacy Solidity 0.7 contracts... │" -echo " └──────────────────────────────────────────────┘" - -SOLC_VERSION="0.7.6" -OPTIMIZE_RUNS=1000000 - - -SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" -ROOT="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd ../../ && pwd -P )" -python3 -m pip install --require-hashes -r "$SCRIPTPATH"/requirements.txt - -solc-select install $SOLC_VERSION -solc-select use $SOLC_VERSION -export SOLC_VERSION=$SOLC_VERSION - - -compileContract () { - local contract - contract=$(basename "$1" ".sol") - - solc --overwrite --optimize --optimize-runs $OPTIMIZE_RUNS --metadata-hash none \ - -o "$ROOT"/contracts/solc/v0.7/"$contract" \ - --abi --bin --allow-paths "$ROOT"/contracts/src/v0.7 \ - "$ROOT"/contracts/src/v0.7/"$1" -} - -compileContract tests/MultiWordConsumer.sol -compileContract Operator.sol -compileContract AuthorizedForwarder.sol -compileContract AuthorizedReceiver.sol -compileContract OperatorFactory.sol -compileContract tests/Consumer.sol -compileContract tests/VRFCoordinatorMock.sol - -# Keeper/Automation -compileContract KeeperRegistry1_1.sol -compileContract KeeperRegistry1_1Mock.sol -compileContract UpkeepRegistrationRequests.sol -compileContract tests/UpkeepPerformCounterRestrictive.sol -compileContract tests/UpkeepCounter.sol \ No newline at end of file diff --git a/contracts/scripts/native_solc_compile_all_transmission b/contracts/scripts/native_solc_compile_all_transmission index 281fa7aea73..9650a2b27d3 100755 --- a/contracts/scripts/native_solc_compile_all_transmission +++ b/contracts/scripts/native_solc_compile_all_transmission @@ -6,7 +6,7 @@ echo " ┌─────────────────────── echo " │ Compiling Transmission contracts... │" echo " └──────────────────────────────────────────────┘" -SOLC_VERSION="0.8.15" +SOLC_VERSION="0.8.19" OPTIMIZE_RUNS=1000000 SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )" diff --git a/contracts/scripts/prepublish_generate_abi_folder b/contracts/scripts/prepublish_generate_abi_folder index bd79c8c9bee..f81b39fd5fa 100755 --- a/contracts/scripts/prepublish_generate_abi_folder +++ b/contracts/scripts/prepublish_generate_abi_folder @@ -9,7 +9,7 @@ SCRIPTPATH="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; cd .. && pwd -P )" TARGET="abi" # For each version directory in src, copy the json files to the correct location -versions=( v0.6 v0.7 v0.8 ) +versions=( v0.8 ) for version in "${versions[@]}" do rm -rf $SCRIPTPATH/$TARGET/$version diff --git a/contracts/src/v0.6/AggregatorFacade.sol b/contracts/src/v0.6/AggregatorFacade.sol deleted file mode 100644 index deae4cfb411..00000000000 --- a/contracts/src/v0.6/AggregatorFacade.sol +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./interfaces/AggregatorV2V3Interface.sol"; - -/** - * @title A facade forAggregator versions to conform to the new v0.6 - * Aggregator V3 interface. - */ -contract AggregatorFacade is AggregatorV2V3Interface { - - AggregatorInterface public aggregator; - uint8 public override decimals; - string public override description; - - uint256 constant public override version = 2; - - // An error specific to the Aggregator V3 Interface, to prevent possible - // confusion around accidentally reading unset values as reported values. - string constant private V3_NO_DATA_ERROR = "No data present"; - - constructor( - address _aggregator, - uint8 _decimals, - string memory _description - ) public { - aggregator = AggregatorInterface(_aggregator); - decimals = _decimals; - description = _description; - } - - /** - * @notice get the latest completed round where the answer was updated - * @dev #[deprecated]. Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestRound() - external - view - virtual - override - returns (uint256) - { - return aggregator.latestRound(); - } - - /** - * @notice Reads the current answer from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestAnswer() - external - view - virtual - override - returns (int256) - { - return aggregator.latestAnswer(); - } - - /** - * @notice Reads the last updated height from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestTimestamp() - external - view - virtual - override - returns (uint256) - { - return aggregator.latestTimestamp(); - } - - /** - * @notice get data about the latest round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt value. - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is always equal to updatedAt because the underlying - * Aggregator contract does not expose this information. - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is always equal to roundId because the underlying - * Aggregator contract does not expose this information. - * @dev Note that for rounds that haven't yet received responses from all - * oracles, answer and updatedAt may change between queries. - */ - function latestRoundData() - external - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return _getRoundData(uint80(aggregator.latestRound())); - } - - /** - * @notice get past rounds answers - * @param _roundId the answer number to retrieve the answer for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getAnswer(uint256 _roundId) - external - view - virtual - override - returns (int256) - { - return aggregator.getAnswer(_roundId); - } - - /** - * @notice get block timestamp when an answer was last updated - * @param _roundId the answer number to retrieve the updated timestamp for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getTimestamp(uint256 _roundId) - external - view - virtual - override - returns (uint256) - { - return aggregator.getTimestamp(_roundId); - } - - /** - * @notice get data about a round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt value. - * @param _roundId the round ID to retrieve the round data for - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is always equal to updatedAt because the underlying - * Aggregator contract does not expose this information. - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is always equal to roundId because the underlying - * Aggregator contract does not expose this information. - * @dev Note that for rounds that haven't yet received responses from all - * oracles, answer and updatedAt may change between queries. - */ - function getRoundData(uint80 _roundId) - external - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return _getRoundData(_roundId); - } - - - /* - * Internal - */ - - function _getRoundData(uint80 _roundId) - internal - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - answer = aggregator.getAnswer(_roundId); - updatedAt = uint64(aggregator.getTimestamp(_roundId)); - - require(updatedAt > 0, V3_NO_DATA_ERROR); - - return (_roundId, answer, updatedAt, updatedAt, _roundId); - } - -} diff --git a/contracts/src/v0.6/AggregatorProxy.sol b/contracts/src/v0.6/AggregatorProxy.sol deleted file mode 100644 index 73de22050c0..00000000000 --- a/contracts/src/v0.6/AggregatorProxy.sol +++ /dev/null @@ -1,445 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./Owned.sol"; -import "./interfaces/AggregatorV2V3Interface.sol"; - -/** - * @title A trusted proxy for updating where current answers are read from - * @notice This contract provides a consistent address for the - * CurrentAnwerInterface but delegates where it reads from to the owner, who is - * trusted to update it. - */ -contract AggregatorProxy is AggregatorV2V3Interface, Owned { - - struct Phase { - uint16 id; - AggregatorV2V3Interface aggregator; - } - Phase private currentPhase; - AggregatorV2V3Interface public proposedAggregator; - mapping(uint16 => AggregatorV2V3Interface) public phaseAggregators; - - uint256 constant private PHASE_OFFSET = 64; - uint256 constant private PHASE_SIZE = 16; - uint256 constant private MAX_ID = 2**(PHASE_OFFSET+PHASE_SIZE) - 1; - - constructor(address _aggregator) public Owned() { - setAggregator(_aggregator); - } - - /** - * @notice Reads the current answer from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestAnswer() - public - view - virtual - override - returns (int256 answer) - { - return currentPhase.aggregator.latestAnswer(); - } - - /** - * @notice Reads the last updated height from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestTimestamp() - public - view - virtual - override - returns (uint256 updatedAt) - { - return currentPhase.aggregator.latestTimestamp(); - } - - /** - * @notice get past rounds answers - * @param _roundId the answer number to retrieve the answer for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getAnswer(uint256 _roundId) - public - view - virtual - override - returns (int256 answer) - { - if (_roundId > MAX_ID) return 0; - - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId); - AggregatorV2V3Interface aggregator = phaseAggregators[phaseId]; - if (address(aggregator) == address(0)) return 0; - - return aggregator.getAnswer(aggregatorRoundId); - } - - /** - * @notice get block timestamp when an answer was last updated - * @param _roundId the answer number to retrieve the updated timestamp for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getTimestamp(uint256 _roundId) - public - view - virtual - override - returns (uint256 updatedAt) - { - if (_roundId > MAX_ID) return 0; - - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId); - AggregatorV2V3Interface aggregator = phaseAggregators[phaseId]; - if (address(aggregator) == address(0)) return 0; - - return aggregator.getTimestamp(aggregatorRoundId); - } - - /** - * @notice get the latest completed round where the answer was updated. This - * ID includes the proxy's phase, to make sure round IDs increase even when - * switching to a newly deployed aggregator. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestRound() - public - view - virtual - override - returns (uint256 roundId) - { - Phase memory phase = currentPhase; // cache storage reads - return addPhase(phase.id, uint64(phase.aggregator.latestRound())); - } - - /** - * @notice get data about a round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @param _roundId the requested round ID as presented through the proxy, this - * is made up of the aggregator's round ID with the phase ID encoded in the - * two highest order bytes - * @return roundId is the round ID from the aggregator for which the data was - * retrieved combined with an phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function getRoundData(uint80 _roundId) - public - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId); - - ( - roundId, - answer, - startedAt, - updatedAt, - answeredInRound - ) = phaseAggregators[phaseId].getRoundData(aggregatorRoundId); - - return addPhaseIds(roundId, answer, startedAt, updatedAt, answeredInRound, phaseId); - } - - /** - * @notice get data about the latest round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @return roundId is the round ID from the aggregator for which the data was - * retrieved combined with an phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function latestRoundData() - public - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - Phase memory current = currentPhase; // cache storage reads - - ( - roundId, - answer, - startedAt, - updatedAt, - answeredInRound - ) = current.aggregator.latestRoundData(); - - return addPhaseIds(roundId, answer, startedAt, updatedAt, answeredInRound, current.id); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @param _roundId the round ID to retrieve the round data for - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedGetRoundData(uint80 _roundId) - public - view - virtual - hasProposal() - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return proposedAggregator.getRoundData(_roundId); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedLatestRoundData() - public - view - virtual - hasProposal() - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return proposedAggregator.latestRoundData(); - } - - /** - * @notice returns the current phase's aggregator address. - */ - function aggregator() - external - view - returns (address) - { - return address(currentPhase.aggregator); - } - - /** - * @notice returns the current phase's ID. - */ - function phaseId() - external - view - returns (uint16) - { - return currentPhase.id; - } - - /** - * @notice represents the number of decimals the aggregator responses represent. - */ - function decimals() - external - view - override - returns (uint8) - { - return currentPhase.aggregator.decimals(); - } - - /** - * @notice the version number representing the type of aggregator the proxy - * points to. - */ - function version() - external - view - override - returns (uint256) - { - return currentPhase.aggregator.version(); - } - - /** - * @notice returns the description of the aggregator the proxy points to. - */ - function description() - external - view - override - returns (string memory) - { - return currentPhase.aggregator.description(); - } - - /** - * @notice Allows the owner to propose a new address for the aggregator - * @param _aggregator The new address for the aggregator contract - */ - function proposeAggregator(address _aggregator) - external - onlyOwner() - { - proposedAggregator = AggregatorV2V3Interface(_aggregator); - } - - /** - * @notice Allows the owner to confirm and change the address - * to the proposed aggregator - * @dev Reverts if the given address doesn't match what was previously - * proposed - * @param _aggregator The new address for the aggregator contract - */ - function confirmAggregator(address _aggregator) - external - onlyOwner() - { - require(_aggregator == address(proposedAggregator), "Invalid proposed aggregator"); - delete proposedAggregator; - setAggregator(_aggregator); - } - - - /* - * Internal - */ - - function setAggregator(address _aggregator) - internal - { - uint16 id = currentPhase.id + 1; - currentPhase = Phase(id, AggregatorV2V3Interface(_aggregator)); - phaseAggregators[id] = AggregatorV2V3Interface(_aggregator); - } - - function addPhase( - uint16 _phase, - uint64 _originalId - ) - internal - pure - returns (uint80) - { - return uint80(uint256(_phase) << PHASE_OFFSET | _originalId); - } - - function parseIds( - uint256 _roundId - ) - internal - pure - returns (uint16, uint64) - { - uint16 phaseId = uint16(_roundId >> PHASE_OFFSET); - uint64 aggregatorRoundId = uint64(_roundId); - - return (phaseId, aggregatorRoundId); - } - - function addPhaseIds( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound, - uint16 phaseId - ) - internal - pure - returns (uint80, int256, uint256, uint256, uint80) - { - return ( - addPhase(phaseId, uint64(roundId)), - answer, - startedAt, - updatedAt, - addPhase(phaseId, uint64(answeredInRound)) - ); - } - - /* - * Modifiers - */ - - modifier hasProposal() { - require(address(proposedAggregator) != address(0), "No proposed aggregator present"); - _; - } - -} \ No newline at end of file diff --git a/contracts/src/v0.6/BlockhashStore.sol b/contracts/src/v0.6/BlockhashStore.sol deleted file mode 100644 index 2da687fb53e..00000000000 --- a/contracts/src/v0.6/BlockhashStore.sol +++ /dev/null @@ -1,80 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./ChainSpecificUtil.sol"; - -/** - * @title BlockhashStore - * @notice This contract provides a way to access blockhashes older than - * the 256 block limit imposed by the BLOCKHASH opcode. - * You may assume that any blockhash stored by the contract is correct. - * Note that the contract depends on the format of serialized Ethereum - * blocks. If a future hardfork of Ethereum changes that format, the - * logic in this contract may become incorrect and an updated version - * would have to be deployed. - */ -contract BlockhashStore { - - mapping(uint => bytes32) internal s_blockhashes; - - /** - * @notice stores blockhash of a given block, assuming it is available through BLOCKHASH - * @param n the number of the block whose blockhash should be stored - */ - function store(uint256 n) public { - bytes32 h = ChainSpecificUtil.getBlockhash(n); - require(h != 0x0, "blockhash(n) failed"); - s_blockhashes[n] = h; - } - - - /** - * @notice stores blockhash of the earliest block still available through BLOCKHASH. - */ - function storeEarliest() external { - store(ChainSpecificUtil.getBlockNumber() - 256); - } - - /** - * @notice stores blockhash after verifying blockheader of child/subsequent block - * @param n the number of the block whose blockhash should be stored - * @param header the rlp-encoded blockheader of block n+1. We verify its correctness by checking - * that it hashes to a stored blockhash, and then extract parentHash to get the n-th blockhash. - */ - function storeVerifyHeader(uint256 n, bytes memory header) public { - require(keccak256(header) == s_blockhashes[n + 1], "header has unknown blockhash"); - - // At this point, we know that header is the correct blockheader for block n+1. - - // The header is an rlp-encoded list. The head item of that list is the 32-byte blockhash of the parent block. - // Based on how rlp works, we know that blockheaders always have the following form: - // 0xf9____a0PARENTHASH... - // ^ ^ ^ - // | | | - // | | +--- PARENTHASH is 32 bytes. rlpenc(PARENTHASH) is 0xa || PARENTHASH. - // | | - // | +--- 2 bytes containing the sum of the lengths of the encoded list items - // | - // +--- 0xf9 because we have a list and (sum of lengths of encoded list items) fits exactly into two bytes. - // - // As a consequence, the PARENTHASH is always at offset 4 of the rlp-encoded block header. - - bytes32 parentHash; - assembly { - parentHash := mload(add(header, 36)) // 36 = 32 byte offset for length prefix of ABI-encoded array - // + 4 byte offset of PARENTHASH (see above) - } - - s_blockhashes[n] = parentHash; - } - - /** - * @notice gets a blockhash from the store. If no hash is known, this function reverts. - * @param n the number of the block whose blockhash should be returned - */ - function getBlockhash(uint256 n) external view returns (bytes32) { - bytes32 h = s_blockhashes[n]; - require(h != 0x0, "blockhash not found in store"); - return h; - } -} diff --git a/contracts/src/v0.6/ChainSpecificUtil.sol b/contracts/src/v0.6/ChainSpecificUtil.sol deleted file mode 100644 index 462531e8af6..00000000000 --- a/contracts/src/v0.6/ChainSpecificUtil.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import {ArbSys} from "./vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; - -//@dev A library that abstracts out opcodes that behave differently across chains. -//@dev The methods below return values that are pertinent to the given chain. -//@dev For instance, ChainSpecificUtil.getBlockNumber() returns L2 block number in L2 chains -library ChainSpecificUtil { - address private constant ARBSYS_ADDR = - address(0x0000000000000000000000000000000000000064); - ArbSys private constant ARBSYS = ArbSys(ARBSYS_ADDR); - uint256 private constant ARB_MAINNET_CHAIN_ID = 42161; - uint256 private constant ARB_GOERLI_TESTNET_CHAIN_ID = 421613; - - function getBlockhash(uint256 blockNumber) internal view returns (bytes32) { - uint256 chainid = getChainID(); - if ( - chainid == ARB_MAINNET_CHAIN_ID || - chainid == ARB_GOERLI_TESTNET_CHAIN_ID - ) { - if ((getBlockNumber() - blockNumber) > 256 || blockNumber >= getBlockNumber()) { - return ""; - } - return ARBSYS.arbBlockHash(blockNumber); - } - return blockhash(blockNumber); - } - - function getBlockNumber() internal view returns (uint256) { - uint256 chainid = getChainID(); - if ( - chainid == ARB_MAINNET_CHAIN_ID || - chainid == ARB_GOERLI_TESTNET_CHAIN_ID - ) { - return ARBSYS.arbBlockNumber(); - } - return block.number; - } - - function getChainID() internal pure returns (uint256) { - uint256 id; - assembly { - id := chainid() - } - return id; - } -} diff --git a/contracts/src/v0.6/Chainlink.sol b/contracts/src/v0.6/Chainlink.sol deleted file mode 100644 index 2665e675634..00000000000 --- a/contracts/src/v0.6/Chainlink.sol +++ /dev/null @@ -1,127 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import { CBORChainlink } from "./vendor/CBORChainlink.sol"; -import { BufferChainlink } from "./vendor/BufferChainlink.sol"; - -/** - * @title Library for common Chainlink functions - * @dev Uses imported CBOR library for encoding to buffer - */ -library Chainlink { - uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase - - using CBORChainlink for BufferChainlink.buffer; - - struct Request { - bytes32 id; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - BufferChainlink.buffer buf; - } - - /** - * @notice Initializes a Chainlink request - * @dev Sets the ID, callback address, and callback function signature on the request - * @param self The uninitialized request - * @param _id The Job Specification ID - * @param _callbackAddress The callback address - * @param _callbackFunction The callback function signature - * @return The initialized request - */ - function initialize( - Request memory self, - bytes32 _id, - address _callbackAddress, - bytes4 _callbackFunction - ) internal pure returns (Chainlink.Request memory) { - BufferChainlink.init(self.buf, defaultBufferSize); - self.id = _id; - self.callbackAddress = _callbackAddress; - self.callbackFunctionId = _callbackFunction; - return self; - } - - /** - * @notice Sets the data for the buffer without encoding CBOR on-chain - * @dev CBOR can be closed with curly-brackets {} or they can be left off - * @param self The initialized request - * @param _data The CBOR data - */ - function setBuffer(Request memory self, bytes memory _data) - internal pure - { - BufferChainlink.init(self.buf, _data.length); - BufferChainlink.append(self.buf, _data); - } - - /** - * @notice Adds a string value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The string value to add - */ - function add(Request memory self, string memory _key, string memory _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeString(_value); - } - - /** - * @notice Adds a bytes value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The bytes value to add - */ - function addBytes(Request memory self, string memory _key, bytes memory _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeBytes(_value); - } - - /** - * @notice Adds a int256 value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The int256 value to add - */ - function addInt(Request memory self, string memory _key, int256 _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeInt(_value); - } - - /** - * @notice Adds a uint256 value to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _value The uint256 value to add - */ - function addUint(Request memory self, string memory _key, uint256 _value) - internal pure - { - self.buf.encodeString(_key); - self.buf.encodeUInt(_value); - } - - /** - * @notice Adds an array of strings to the request with a given key name - * @param self The initialized request - * @param _key The name of the key - * @param _values The array of string values to add - */ - function addStringArray(Request memory self, string memory _key, string[] memory _values) - internal pure - { - self.buf.encodeString(_key); - self.buf.startArray(); - for (uint256 i = 0; i < _values.length; i++) { - self.buf.encodeString(_values[i]); - } - self.buf.endSequence(); - } -} diff --git a/contracts/src/v0.6/ChainlinkClient.sol b/contracts/src/v0.6/ChainlinkClient.sol deleted file mode 100644 index 079e05ef5f1..00000000000 --- a/contracts/src/v0.6/ChainlinkClient.sol +++ /dev/null @@ -1,262 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./Chainlink.sol"; -import "./interfaces/ENSInterface.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/ChainlinkRequestInterface.sol"; -import "./interfaces/PointerInterface.sol"; -import { ENSResolver as ENSResolver_Chainlink } from "./vendor/ENSResolver.sol"; - -/** - * @title The ChainlinkClient contract - * @notice Contract writers can inherit this contract in order to create requests for the - * Chainlink network - */ -contract ChainlinkClient { - using Chainlink for Chainlink.Request; - - uint256 constant internal LINK = 10**18; - uint256 constant private AMOUNT_OVERRIDE = 0; - address constant private SENDER_OVERRIDE = address(0); - uint256 constant private ARGS_VERSION = 1; - bytes32 constant private ENS_TOKEN_SUBNAME = keccak256("link"); - bytes32 constant private ENS_ORACLE_SUBNAME = keccak256("oracle"); - address constant private LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; - - ENSInterface private ens; - bytes32 private ensNode; - LinkTokenInterface private link; - ChainlinkRequestInterface private oracle; - uint256 private requestCount = 1; - mapping(bytes32 => address) private pendingRequests; - - event ChainlinkRequested(bytes32 indexed id); - event ChainlinkFulfilled(bytes32 indexed id); - event ChainlinkCancelled(bytes32 indexed id); - - /** - * @notice Creates a request that can hold additional parameters - * @param _specId The Job Specification ID that the request will be created for - * @param _callbackAddress The callback address that the response will be sent to - * @param _callbackFunctionSignature The callback function signature to use for the callback address - * @return A Chainlink Request struct in memory - */ - function buildChainlinkRequest( - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunctionSignature - ) internal pure returns (Chainlink.Request memory) { - Chainlink.Request memory req; - return req.initialize(_specId, _callbackAddress, _callbackFunctionSignature); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev Calls `chainlinkRequestTo` with the stored oracle address - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequest(Chainlink.Request memory _req, uint256 _payment) - internal - returns (bytes32) - { - return sendChainlinkRequestTo(address(oracle), _req, _payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param _oracle The address of the oracle for the request - * @param _req The initialized Chainlink Request - * @param _payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequestTo(address _oracle, Chainlink.Request memory _req, uint256 _payment) - internal - returns (bytes32 requestId) - { - requestId = keccak256(abi.encodePacked(this, requestCount)); - _req.nonce = requestCount; - pendingRequests[requestId] = _oracle; - emit ChainlinkRequested(requestId); - require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle"); - requestCount += 1; - - return requestId; - } - - /** - * @notice Allows a request to be cancelled if it has not been fulfilled - * @dev Requires keeping track of the expiration value emitted from the oracle contract. - * Deletes the request from the `pendingRequests` mapping. - * Emits ChainlinkCancelled event. - * @param _requestId The request ID - * @param _payment The amount of LINK sent for the request - * @param _callbackFunc The callback function specified for the request - * @param _expiration The time of the expiration for the request - */ - function cancelChainlinkRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunc, - uint256 _expiration - ) - internal - { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(pendingRequests[_requestId]); - delete pendingRequests[_requestId]; - emit ChainlinkCancelled(_requestId); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunc, _expiration); - } - - /** - * @notice Sets the stored oracle address - * @param _oracle The address of the oracle contract - */ - function setChainlinkOracle(address _oracle) internal { - oracle = ChainlinkRequestInterface(_oracle); - } - - /** - * @notice Sets the LINK token address - * @param _link The address of the LINK token contract - */ - function setChainlinkToken(address _link) internal { - link = LinkTokenInterface(_link); - } - - /** - * @notice Sets the Chainlink token address for the public - * network as given by the Pointer contract - */ - function setPublicChainlinkToken() internal { - setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); - } - - /** - * @notice Retrieves the stored address of the LINK token - * @return The address of the LINK token - */ - function chainlinkTokenAddress() - internal - view - returns (address) - { - return address(link); - } - - /** - * @notice Retrieves the stored address of the oracle contract - * @return The address of the oracle contract - */ - function chainlinkOracleAddress() - internal - view - returns (address) - { - return address(oracle); - } - - /** - * @notice Allows for a request which was created on another contract to be fulfilled - * on this contract - * @param _oracle The address of the oracle contract that will fulfill the request - * @param _requestId The request ID used for the response - */ - function addChainlinkExternalRequest(address _oracle, bytes32 _requestId) - internal - notPendingRequest(_requestId) - { - pendingRequests[_requestId] = _oracle; - } - - /** - * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS - * @dev Accounts for subnodes having different resolvers - * @param _ens The address of the ENS contract - * @param _node The ENS node hash - */ - function useChainlinkWithENS(address _ens, bytes32 _node) - internal - { - ens = ENSInterface(_ens); - ensNode = _node; - bytes32 linkSubnode = keccak256(abi.encodePacked(ensNode, ENS_TOKEN_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(linkSubnode)); - setChainlinkToken(resolver.addr(linkSubnode)); - updateChainlinkOracleWithENS(); - } - - /** - * @notice Sets the stored oracle contract with the address resolved by ENS - * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously - */ - function updateChainlinkOracleWithENS() - internal - { - bytes32 oracleSubnode = keccak256(abi.encodePacked(ensNode, ENS_ORACLE_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(ens.resolver(oracleSubnode)); - setChainlinkOracle(resolver.addr(oracleSubnode)); - } - - /** - * @notice Encodes the request to be sent to the oracle contract - * @dev The Chainlink node expects values to be in order for the request to be picked up. Order of types - * will be validated in the oracle contract. - * @param _req The initialized Chainlink Request - * @return The bytes payload for the `transferAndCall` method - */ - function encodeRequest(Chainlink.Request memory _req) - private - view - returns (bytes memory) - { - return abi.encodeWithSelector( - oracle.oracleRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - _req.id, - _req.callbackAddress, - _req.callbackFunctionId, - _req.nonce, - ARGS_VERSION, - _req.buf.buf); - } - - /** - * @notice Ensures that the fulfillment is valid for this contract - * @dev Use if the contract developer prefers methods instead of modifiers for validation - * @param _requestId The request ID for fulfillment - */ - function validateChainlinkCallback(bytes32 _requestId) - internal - recordChainlinkFulfillment(_requestId) - // solhint-disable-next-line no-empty-blocks - {} - - /** - * @dev Reverts if the sender is not the oracle of the request. - * Emits ChainlinkFulfilled event. - * @param _requestId The request ID for fulfillment - */ - modifier recordChainlinkFulfillment(bytes32 _requestId) { - require(msg.sender == pendingRequests[_requestId], - "Source must be the oracle of the request"); - delete pendingRequests[_requestId]; - emit ChainlinkFulfilled(_requestId); - _; - } - - /** - * @dev Reverts if the request is already pending - * @param _requestId The request ID for fulfillment - */ - modifier notPendingRequest(bytes32 _requestId) { - require(pendingRequests[_requestId] == address(0), "Request is already pending"); - _; - } -} diff --git a/contracts/src/v0.6/CheckedMath.sol b/contracts/src/v0.6/CheckedMath.sol deleted file mode 100644 index 3f622797f7e..00000000000 --- a/contracts/src/v0.6/CheckedMath.sol +++ /dev/null @@ -1,87 +0,0 @@ -// SPDX-License-Identifier: MIT -// Adapted from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/97894a140d2a698e5a0f913648a8f56d62277a70/contracts/math/SignedSafeMath.sol - -pragma solidity ^0.6.0; - -library CheckedMath { - - int256 constant internal INT256_MIN = -2**255; - - /** - * @dev Subtracts two signed integers, returns false 2nd param on overflow. - */ - function add( - int256 a, - int256 b - ) - internal - pure - returns (int256 result, bool ok) - { - int256 c = a + b; - if ((b >= 0 && c < a) || (b < 0 && c >= a)) return (0, false); - - return (c, true); - } - - /** - * @dev Subtracts two signed integers, returns false 2nd param on overflow. - */ - function sub( - int256 a, - int256 b - ) - internal - pure - returns (int256 result, bool ok) - { - int256 c = a - b; - if ((b < 0 && c <= a) || (b >= 0 && c > a)) return (0, false); - - return (c, true); - } - - - /** - * @dev Multiplies two signed integers, returns false 2nd param on overflow. - */ - function mul( - int256 a, - int256 b - ) - internal - pure - returns (int256 result, bool ok) - { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) return (0, true); - if (a == -1 && b == INT256_MIN) return (0, false); - - int256 c = a * b; - if (!(c / a == b)) return (0, false); - - return (c, true); - } - - /** - * @dev Divides two signed integers, returns false 2nd param on overflow. - */ - function div( - int256 a, - int256 b - ) - internal - pure - returns (int256 result, bool ok) - { - if (b == 0) return (0, false); - if (b == -1 && a == INT256_MIN) return (0, false); - - int256 c = a / b; - - return (c, true); - } - -} diff --git a/contracts/src/v0.6/Denominations.sol b/contracts/src/v0.6/Denominations.sol deleted file mode 100644 index 339997d3479..00000000000 --- a/contracts/src/v0.6/Denominations.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.6.0; - -library Denominations { - address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; - - // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217 - address public constant USD = address(840); - address public constant GBP = address(826); - address public constant EUR = address(978); - address public constant JPY = address(392); - address public constant KRW = address(410); - address public constant CNY = address(156); - address public constant AUD = address(36); - address public constant CAD = address(124); - address public constant CHF = address(756); - address public constant ARS = address(32); - address public constant PHP = address(608); - address public constant NZD = address(554); - address public constant SGD = address(702); - address public constant NGN = address(566); - address public constant ZAR = address(710); - address public constant RUB = address(643); - address public constant INR = address(356); - address public constant BRL = address(986); -} diff --git a/contracts/src/v0.6/DeviationFlaggingValidator.sol b/contracts/src/v0.6/DeviationFlaggingValidator.sol deleted file mode 100644 index be2b2b1af8e..00000000000 --- a/contracts/src/v0.6/DeviationFlaggingValidator.sol +++ /dev/null @@ -1,160 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./Owned.sol"; -import "./CheckedMath.sol"; -import "./interfaces/AggregatorValidatorInterface.sol"; -import "./interfaces/FlagsInterface.sol"; - -/** - * @title The Deviation Flagging Validator contract - * @notice Checks the current value against the previous value, and makes sure - * that it does not deviate outside of some relative range. If the deviation - * threshold is passed then the validator raises a flag on the designated - * flag contract. - */ -contract DeviationFlaggingValidator is Owned, AggregatorValidatorInterface { - using CheckedMath for int256; - - uint32 constant public THRESHOLD_MULTIPLIER = 100000; - - uint32 public flaggingThreshold; - FlagsInterface public flags; - - event FlaggingThresholdUpdated( - uint24 indexed previous, - uint24 indexed current - ); - event FlagsAddressUpdated( - address indexed previous, - address indexed current - ); - - int256 constant private INT256_MIN = -2**255; - - /** - * @notice sets up the validator with its threshold and flag address. - * @param _flags sets the address of the flags contract - * @param _flaggingThreshold sets the threshold that will trigger a flag to be - * raised. Setting the value of 100,000 is equivalent to tolerating a 100% - * change compared to the previous price. - */ - constructor( - address _flags, - uint24 _flaggingThreshold - ) - public - { - setFlagsAddress(_flags); - setFlaggingThreshold(_flaggingThreshold); - } - - /** - * @notice checks whether the parameters count as valid by comparing the - * difference change to the flagging threshold. - * @param _previousRoundId is ignored. - * @param _previousAnswer is used as the median of the difference with the - * current answer to determine if the deviation threshold has been exceeded. - * @param _roundId is ignored. - * @param _answer is the latest answer which is compared for a ratio of change - * to make sure it has not exceeded the flagging threshold. - */ - function validate( - uint256 _previousRoundId, - int256 _previousAnswer, - uint256 _roundId, - int256 _answer - ) - external - override - returns (bool) - { - if (!isValid(_previousRoundId, _previousAnswer, _roundId, _answer)) { - flags.raiseFlag(msg.sender); - return false; - } - - return true; - } - - /** - * @notice checks whether the parameters count as valid by comparing the - * difference change to the flagging threshold and raises a flag on the - * flagging contract if so. - * @param _previousAnswer is used as the median of the difference with the - * current answer to determine if the deviation threshold has been exceeded. - * @param _answer is the current answer which is compared for a ratio of - * change * to make sure it has not exceeded the flagging threshold. - */ - function isValid( - uint256 , - int256 _previousAnswer, - uint256 , - int256 _answer - ) - public - view - returns (bool) - { - if (_previousAnswer == 0) return true; - - (int256 change, bool changeOk) = _previousAnswer.sub(_answer); - (int256 ratioNumerator, bool numOk) = change.mul(THRESHOLD_MULTIPLIER); - (int256 ratio, bool ratioOk) = ratioNumerator.div(_previousAnswer); - (uint256 absRatio, bool absOk) = abs(ratio); - - return changeOk && numOk && ratioOk && absOk && absRatio <= flaggingThreshold; - } - - /** - * @notice updates the flagging threshold - * @param _flaggingThreshold sets the threshold that will trigger a flag to be - * raised. Setting the value of 100,000 is equivalent to tolerating a 100% - * change compared to the previous price. - */ - function setFlaggingThreshold(uint24 _flaggingThreshold) - public - onlyOwner() - { - uint24 previousFT = uint24(flaggingThreshold); - - if (previousFT != _flaggingThreshold) { - flaggingThreshold = _flaggingThreshold; - - emit FlaggingThresholdUpdated(previousFT, _flaggingThreshold); - } - } - - /** - * @notice updates the flagging contract address for raising flags - * @param _flags sets the address of the flags contract - */ - function setFlagsAddress(address _flags) - public - onlyOwner() - { - address previous = address(flags); - - if (previous != _flags) { - flags = FlagsInterface(_flags); - - emit FlagsAddressUpdated(previous, _flags); - } - } - - - // PRIVATE - - function abs( - int256 value - ) - private - pure - returns (uint256, bool) - { - if (value >= 0) return (uint256(value), true); - if (value == CheckedMath.INT256_MIN) return (0, false); - return (uint256(value * -1), true); - } - -} diff --git a/contracts/src/v0.6/EACAggregatorProxy.sol b/contracts/src/v0.6/EACAggregatorProxy.sol deleted file mode 100644 index f1c0e8bcfd4..00000000000 --- a/contracts/src/v0.6/EACAggregatorProxy.sol +++ /dev/null @@ -1,282 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./AggregatorProxy.sol"; -import "./interfaces/AccessControllerInterface.sol"; - -/** - * @title External Access Controlled Aggregator Proxy - * @notice A trusted proxy for updating where current answers are read from - * @notice This contract provides a consistent address for the - * Aggregator and AggregatorV3Interface but delegates where it reads from to the owner, who is - * trusted to update it. - * @notice Only access enabled addresses are allowed to access getters for - * aggregated answers and round information. - */ -contract EACAggregatorProxy is AggregatorProxy { - - AccessControllerInterface public accessController; - - constructor( - address _aggregator, - address _accessController - ) - public - AggregatorProxy(_aggregator) - { - setController(_accessController); - } - - /** - * @notice Allows the owner to update the accessController contract address. - * @param _accessController The new address for the accessController contract - */ - function setController(address _accessController) - public - onlyOwner() - { - accessController = AccessControllerInterface(_accessController); - } - - /** - * @notice Reads the current answer from aggregator delegated to. - * @dev overridden function to add the checkAccess() modifier - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestAnswer() - public - view - override - checkAccess() - returns (int256) - { - return super.latestAnswer(); - } - - /** - * @notice get the latest completed round where the answer was updated. This - * ID includes the proxy's phase, to make sure round IDs increase even when - * switching to a newly deployed aggregator. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestTimestamp() - public - view - override - checkAccess() - returns (uint256) - { - return super.latestTimestamp(); - } - - /** - * @notice get past rounds answers - * @param _roundId the answer number to retrieve the answer for - * @dev overridden function to add the checkAccess() modifier - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getAnswer(uint256 _roundId) - public - view - override - checkAccess() - returns (int256) - { - return super.getAnswer(_roundId); - } - - /** - * @notice get block timestamp when an answer was last updated - * @param _roundId the answer number to retrieve the updated timestamp for - * @dev overridden function to add the checkAccess() modifier - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getTimestamp(uint256 _roundId) - public - view - override - checkAccess() - returns (uint256) - { - return super.getTimestamp(_roundId); - } - - /** - * @notice get the latest completed round where the answer was updated - * @dev overridden function to add the checkAccess() modifier - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestRound() - public - view - override - checkAccess() - returns (uint256) - { - return super.latestRound(); - } - - /** - * @notice get data about a round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @param _roundId the round ID to retrieve the round data for - * @return roundId is the round ID from the aggregator for which the data was - * retrieved combined with a phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function getRoundData(uint80 _roundId) - public - view - checkAccess() - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return super.getRoundData(_roundId); - } - - /** - * @notice get data about the latest round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @return roundId is the round ID from the aggregator for which the data was - * retrieved combined with a phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function latestRoundData() - public - view - checkAccess() - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return super.latestRoundData(); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @param _roundId the round ID to retrieve the round data for - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedGetRoundData(uint80 _roundId) - public - view - checkAccess() - hasProposal() - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return super.proposedGetRoundData(_roundId); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedLatestRoundData() - public - view - checkAccess() - hasProposal() - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return super.proposedLatestRoundData(); - } - - /** - * @dev reverts if the caller does not have access by the accessController - * contract or is the contract itself. - */ - modifier checkAccess() { - AccessControllerInterface ac = accessController; - require(address(ac) == address(0) || ac.hasAccess(msg.sender, msg.data), "No access"); - _; - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/Flags.sol b/contracts/src/v0.6/Flags.sol deleted file mode 100644 index ce8c9d5fda2..00000000000 --- a/contracts/src/v0.6/Flags.sol +++ /dev/null @@ -1,174 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - - -import "./SimpleReadAccessController.sol"; -import "./interfaces/AccessControllerInterface.sol"; -import "./interfaces/FlagsInterface.sol"; - - -/** - * @title The Flags contract - * @notice Allows flags to signal to any reader on the access control list. - * The owner can set flags, or designate other addresses to set flags. The - * owner must turn the flags off, other setters cannot. An expected pattern is - * to allow addresses to raise flags on themselves, so if you are subscribing to - * FlagOn events you should filter for addresses you care about. - */ -contract Flags is FlagsInterface, SimpleReadAccessController { - - AccessControllerInterface public raisingAccessController; - - mapping(address => bool) private flags; - - event FlagRaised( - address indexed subject - ); - event FlagLowered( - address indexed subject - ); - event RaisingAccessControllerUpdated( - address indexed previous, - address indexed current - ); - - /** - * @param racAddress address for the raising access controller. - */ - constructor( - address racAddress - ) - public - { - setRaisingAccessController(racAddress); - } - - /** - * @notice read the warning flag status of a contract address. - * @param subject The contract address being checked for a flag. - * @return A true value indicates that a flag was raised and a - * false value indicates that no flag was raised. - */ - function getFlag(address subject) - external - view - override - checkAccess() - returns (bool) - { - return flags[subject]; - } - - /** - * @notice read the warning flag status of a contract address. - * @param subjects An array of addresses being checked for a flag. - * @return An array of bools where a true value for any flag indicates that - * a flag was raised and a false value indicates that no flag was raised. - */ - function getFlags(address[] calldata subjects) - external - view - override - checkAccess() - returns (bool[] memory) - { - bool[] memory responses = new bool[](subjects.length); - for (uint256 i = 0; i < subjects.length; i++) { - responses[i] = flags[subjects[i]]; - } - return responses; - } - - /** - * @notice enable the warning flag for an address. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subject The contract address whose flag is being raised - */ - function raiseFlag(address subject) - external - override - { - require(allowedToRaiseFlags(), "Not allowed to raise flags"); - - tryToRaiseFlag(subject); - } - - /** - * @notice enable the warning flags for multiple addresses. - * Access is controlled by raisingAccessController, except for owner - * who always has access. - * @param subjects List of the contract addresses whose flag is being raised - */ - function raiseFlags(address[] calldata subjects) - external - override - { - require(allowedToRaiseFlags(), "Not allowed to raise flags"); - - for (uint256 i = 0; i < subjects.length; i++) { - tryToRaiseFlag(subjects[i]); - } - } - - /** - * @notice allows owner to disable the warning flags for multiple addresses. - * @param subjects List of the contract addresses whose flag is being lowered - */ - function lowerFlags(address[] calldata subjects) - external - override - onlyOwner() - { - for (uint256 i = 0; i < subjects.length; i++) { - address subject = subjects[i]; - - if (flags[subject]) { - flags[subject] = false; - emit FlagLowered(subject); - } - } - } - - /** - * @notice allows owner to change the access controller for raising flags. - * @param racAddress new address for the raising access controller. - */ - function setRaisingAccessController( - address racAddress - ) - public - override - onlyOwner() - { - address previous = address(raisingAccessController); - - if (previous != racAddress) { - raisingAccessController = AccessControllerInterface(racAddress); - - emit RaisingAccessControllerUpdated(previous, racAddress); - } - } - - - // PRIVATE - - function allowedToRaiseFlags() - private - view - returns (bool) - { - return msg.sender == owner || - raisingAccessController.hasAccess(msg.sender, msg.data); - } - - function tryToRaiseFlag(address subject) - private - { - if (!flags[subject]) { - flags[subject] = true; - emit FlagRaised(subject); - } - } - -} diff --git a/contracts/src/v0.6/FluxAggregator.sol b/contracts/src/v0.6/FluxAggregator.sol deleted file mode 100644 index afe4731a6a7..00000000000 --- a/contracts/src/v0.6/FluxAggregator.sol +++ /dev/null @@ -1,1053 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./Median.sol"; -import "./Owned.sol"; -import "./SafeMath128.sol"; -import "./SafeMath32.sol"; -import "./SafeMath64.sol"; -import "./interfaces/AggregatorV2V3Interface.sol"; -import "./interfaces/AggregatorValidatorInterface.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./vendor/SafeMathChainlink.sol"; - -/** - * @title The Prepaid Aggregator contract - * @notice Handles aggregating data pushed in from off-chain, and unlocks - * payment for oracles as they report. Oracles' submissions are gathered in - * rounds, with each round aggregating the submissions for each oracle into a - * single answer. The latest aggregated answer is exposed as well as historical - * answers and their updated at timestamp. - */ -contract FluxAggregator is AggregatorV2V3Interface, Owned { - using SafeMathChainlink for uint256; - using SafeMath128 for uint128; - using SafeMath64 for uint64; - using SafeMath32 for uint32; - - struct Round { - int256 answer; - uint64 startedAt; - uint64 updatedAt; - uint32 answeredInRound; - } - - struct RoundDetails { - int256[] submissions; - uint32 maxSubmissions; - uint32 minSubmissions; - uint32 timeout; - uint128 paymentAmount; - } - - struct OracleStatus { - uint128 withdrawable; - uint32 startingRound; - uint32 endingRound; - uint32 lastReportedRound; - uint32 lastStartedRound; - int256 latestSubmission; - uint16 index; - address admin; - address pendingAdmin; - } - - struct Requester { - bool authorized; - uint32 delay; - uint32 lastStartedRound; - } - - struct Funds { - uint128 available; - uint128 allocated; - } - - LinkTokenInterface public linkToken; - AggregatorValidatorInterface public validator; - - // Round related params - uint128 public paymentAmount; - uint32 public maxSubmissionCount; - uint32 public minSubmissionCount; - uint32 public restartDelay; - uint32 public timeout; - uint8 public override decimals; - string public override description; - - int256 immutable public minSubmissionValue; - int256 immutable public maxSubmissionValue; - - uint256 constant public override version = 3; - - /** - * @notice To ensure owner isn't withdrawing required funds as oracles are - * submitting updates, we enforce that the contract maintains a minimum - * reserve of RESERVE_ROUNDS * oracleCount() LINK earmarked for payment to - * oracles. (Of course, this doesn't prevent the contract from running out of - * funds without the owner's intervention.) - */ - uint256 constant private RESERVE_ROUNDS = 2; - uint256 constant private MAX_ORACLE_COUNT = 77; - uint32 constant private ROUND_MAX = 2**32-1; - uint256 private constant VALIDATOR_GAS_LIMIT = 100000; - // An error specific to the Aggregator V3 Interface, to prevent possible - // confusion around accidentally reading unset values as reported values. - string constant private V3_NO_DATA_ERROR = "No data present"; - - uint32 private reportingRoundId; - uint32 internal latestRoundId; - mapping(address => OracleStatus) private oracles; - mapping(uint32 => Round) internal rounds; - mapping(uint32 => RoundDetails) internal details; - mapping(address => Requester) internal requesters; - address[] private oracleAddresses; - Funds private recordedFunds; - - event AvailableFundsUpdated( - uint256 indexed amount - ); - event RoundDetailsUpdated( - uint128 indexed paymentAmount, - uint32 indexed minSubmissionCount, - uint32 indexed maxSubmissionCount, - uint32 restartDelay, - uint32 timeout // measured in seconds - ); - event OraclePermissionsUpdated( - address indexed oracle, - bool indexed whitelisted - ); - event OracleAdminUpdated( - address indexed oracle, - address indexed newAdmin - ); - event OracleAdminUpdateRequested( - address indexed oracle, - address admin, - address newAdmin - ); - event SubmissionReceived( - int256 indexed submission, - uint32 indexed round, - address indexed oracle - ); - event RequesterPermissionsSet( - address indexed requester, - bool authorized, - uint32 delay - ); - event ValidatorUpdated( - address indexed previous, - address indexed current - ); - - /** - * @notice set up the aggregator with initial configuration - * @param _link The address of the LINK token - * @param _paymentAmount The amount paid of LINK paid to each oracle per submission, in wei (units of 10⁻¹⁸ LINK) - * @param _timeout is the number of seconds after the previous round that are - * allowed to lapse before allowing an oracle to skip an unfinished round - * @param _validator is an optional contract address for validating - * external validation of answers - * @param _minSubmissionValue is an immutable check for a lower bound of what - * submission values are accepted from an oracle - * @param _maxSubmissionValue is an immutable check for an upper bound of what - * submission values are accepted from an oracle - * @param _decimals represents the number of decimals to offset the answer by - * @param _description a short description of what is being reported - */ - constructor( - address _link, - uint128 _paymentAmount, - uint32 _timeout, - address _validator, - int256 _minSubmissionValue, - int256 _maxSubmissionValue, - uint8 _decimals, - string memory _description - ) public { - linkToken = LinkTokenInterface(_link); - updateFutureRounds(_paymentAmount, 0, 0, 0, _timeout); - setValidator(_validator); - minSubmissionValue = _minSubmissionValue; - maxSubmissionValue = _maxSubmissionValue; - decimals = _decimals; - description = _description; - rounds[0].updatedAt = uint64(block.timestamp.sub(uint256(_timeout))); - } - - /** - * @notice called by oracles when they have witnessed a need to update - * @param _roundId is the ID of the round this submission pertains to - * @param _submission is the updated data that the oracle is submitting - */ - function submit(uint256 _roundId, int256 _submission) - external - { - bytes memory error = validateOracleRound(msg.sender, uint32(_roundId)); - require(_submission >= minSubmissionValue, "value below minSubmissionValue"); - require(_submission <= maxSubmissionValue, "value above maxSubmissionValue"); - require(error.length == 0, string(error)); - - oracleInitializeNewRound(uint32(_roundId)); - recordSubmission(_submission, uint32(_roundId)); - (bool updated, int256 newAnswer) = updateRoundAnswer(uint32(_roundId)); - payOracle(uint32(_roundId)); - deleteRoundDetails(uint32(_roundId)); - if (updated) { - validateAnswer(uint32(_roundId), newAnswer); - } - } - - /** - * @notice called by the owner to remove and add new oracles as well as - * update the round related parameters that pertain to total oracle count - * @param _removed is the list of addresses for the new Oracles being removed - * @param _added is the list of addresses for the new Oracles being added - * @param _addedAdmins is the admin addresses for the new respective _added - * list. Only this address is allowed to access the respective oracle's funds - * @param _minSubmissions is the new minimum submission count for each round - * @param _maxSubmissions is the new maximum submission count for each round - * @param _restartDelay is the number of rounds an Oracle has to wait before - * they can initiate a round - */ - function changeOracles( - address[] calldata _removed, - address[] calldata _added, - address[] calldata _addedAdmins, - uint32 _minSubmissions, - uint32 _maxSubmissions, - uint32 _restartDelay - ) - external - onlyOwner() - { - for (uint256 i = 0; i < _removed.length; i++) { - removeOracle(_removed[i]); - } - - require(_added.length == _addedAdmins.length, "need same oracle and admin count"); - require(uint256(oracleCount()).add(_added.length) <= MAX_ORACLE_COUNT, "max oracles allowed"); - - for (uint256 i = 0; i < _added.length; i++) { - addOracle(_added[i], _addedAdmins[i]); - } - - updateFutureRounds(paymentAmount, _minSubmissions, _maxSubmissions, _restartDelay, timeout); - } - - /** - * @notice update the round and payment related parameters for subsequent - * rounds - * @param _paymentAmount is the payment amount for subsequent rounds - * @param _minSubmissions is the new minimum submission count for each round - * @param _maxSubmissions is the new maximum submission count for each round - * @param _restartDelay is the number of rounds an Oracle has to wait before - * they can initiate a round - */ - function updateFutureRounds( - uint128 _paymentAmount, - uint32 _minSubmissions, - uint32 _maxSubmissions, - uint32 _restartDelay, - uint32 _timeout - ) - public - onlyOwner() - { - uint32 oracleNum = oracleCount(); // Save on storage reads - require(_maxSubmissions >= _minSubmissions, "max must equal/exceed min"); - require(oracleNum >= _maxSubmissions, "max cannot exceed total"); - require(oracleNum == 0 || oracleNum > _restartDelay, "delay cannot exceed total"); - require(recordedFunds.available >= requiredReserve(_paymentAmount), "insufficient funds for payment"); - if (oracleCount() > 0) { - require(_minSubmissions > 0, "min must be greater than 0"); - } - - paymentAmount = _paymentAmount; - minSubmissionCount = _minSubmissions; - maxSubmissionCount = _maxSubmissions; - restartDelay = _restartDelay; - timeout = _timeout; - - emit RoundDetailsUpdated( - paymentAmount, - _minSubmissions, - _maxSubmissions, - _restartDelay, - _timeout - ); - } - - /** - * @notice the amount of payment yet to be withdrawn by oracles - */ - function allocatedFunds() - external - view - returns (uint128) - { - return recordedFunds.allocated; - } - - /** - * @notice the amount of future funding available to oracles - */ - function availableFunds() - external - view - returns (uint128) - { - return recordedFunds.available; - } - - /** - * @notice recalculate the amount of LINK available for payouts - */ - function updateAvailableFunds() - public - { - Funds memory funds = recordedFunds; - - uint256 nowAvailable = linkToken.balanceOf(address(this)).sub(funds.allocated); - - if (funds.available != nowAvailable) { - recordedFunds.available = uint128(nowAvailable); - emit AvailableFundsUpdated(nowAvailable); - } - } - - /** - * @notice returns the number of oracles - */ - function oracleCount() public view returns (uint8) { - return uint8(oracleAddresses.length); - } - - /** - * @notice returns an array of addresses containing the oracles on contract - */ - function getOracles() external view returns (address[] memory) { - return oracleAddresses; - } - - /** - * @notice get the most recently reported answer - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestAnswer() - public - view - virtual - override - returns (int256) - { - return rounds[latestRoundId].answer; - } - - /** - * @notice get the most recent updated at timestamp - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestTimestamp() - public - view - virtual - override - returns (uint256) - { - return rounds[latestRoundId].updatedAt; - } - - /** - * @notice get the ID of the last updated round - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestRound() - public - view - virtual - override - returns (uint256) - { - return latestRoundId; - } - - /** - * @notice get past rounds answers - * @param _roundId the round number to retrieve the answer for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getAnswer(uint256 _roundId) - public - view - virtual - override - returns (int256) - { - if (validRoundId(_roundId)) { - return rounds[uint32(_roundId)].answer; - } - return 0; - } - - /** - * @notice get timestamp when an answer was last updated - * @param _roundId the round number to retrieve the updated timestamp for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getTimestamp(uint256 _roundId) - public - view - virtual - override - returns (uint256) - { - if (validRoundId(_roundId)) { - return rounds[uint32(_roundId)].updatedAt; - } - return 0; - } - - /** - * @notice get data about a round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * @param _roundId the round ID to retrieve the round data for - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. This is 0 - * if the round hasn't been started yet. - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. answeredInRound may be smaller than roundId when the round - * timed out. answeredInRound is equal to roundId when the round didn't time out - * and was completed regularly. - * @dev Note that for in-progress rounds (i.e. rounds that haven't yet received - * maxSubmissions) answer and updatedAt may change between queries. - */ - function getRoundData(uint80 _roundId) - public - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - Round memory r = rounds[uint32(_roundId)]; - - require(r.answeredInRound > 0 && validRoundId(_roundId), V3_NO_DATA_ERROR); - - return ( - _roundId, - r.answer, - r.startedAt, - r.updatedAt, - r.answeredInRound - ); - } - - /** - * @notice get data about the latest round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. Consumers are encouraged to - * use this more fully featured method over the "legacy" latestRound/ - * latestAnswer/latestTimestamp functions. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * @return roundId is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. This is 0 - * if the round hasn't been started yet. - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. answeredInRound may be smaller than roundId when the round - * timed out. answeredInRound is equal to roundId when the round didn't time - * out and was completed regularly. - * @dev Note that for in-progress rounds (i.e. rounds that haven't yet - * received maxSubmissions) answer and updatedAt may change between queries. - */ - function latestRoundData() - public - view - virtual - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return getRoundData(latestRoundId); - } - - - /** - * @notice query the available amount of LINK for an oracle to withdraw - */ - function withdrawablePayment(address _oracle) - external - view - returns (uint256) - { - return oracles[_oracle].withdrawable; - } - - /** - * @notice transfers the oracle's LINK to another address. Can only be called - * by the oracle's admin. - * @param _oracle is the oracle whose LINK is transferred - * @param _recipient is the address to send the LINK to - * @param _amount is the amount of LINK to send - */ - function withdrawPayment(address _oracle, address _recipient, uint256 _amount) - external - { - require(oracles[_oracle].admin == msg.sender, "only callable by admin"); - - // Safe to downcast _amount because the total amount of LINK is less than 2^128. - uint128 amount = uint128(_amount); - uint128 available = oracles[_oracle].withdrawable; - require(available >= amount, "insufficient withdrawable funds"); - - oracles[_oracle].withdrawable = available.sub(amount); - recordedFunds.allocated = recordedFunds.allocated.sub(amount); - - assert(linkToken.transfer(_recipient, uint256(amount))); - } - - /** - * @notice transfers the owner's LINK to another address - * @param _recipient is the address to send the LINK to - * @param _amount is the amount of LINK to send - */ - function withdrawFunds(address _recipient, uint256 _amount) - external - onlyOwner() - { - uint256 available = uint256(recordedFunds.available); - require(available.sub(requiredReserve(paymentAmount)) >= _amount, "insufficient reserve funds"); - require(linkToken.transfer(_recipient, _amount), "token transfer failed"); - updateAvailableFunds(); - } - - /** - * @notice get the admin address of an oracle - * @param _oracle is the address of the oracle whose admin is being queried - */ - function getAdmin(address _oracle) - external - view - returns (address) - { - return oracles[_oracle].admin; - } - - /** - * @notice transfer the admin address for an oracle - * @param _oracle is the address of the oracle whose admin is being transferred - * @param _newAdmin is the new admin address - */ - function transferAdmin(address _oracle, address _newAdmin) - external - { - require(oracles[_oracle].admin == msg.sender, "only callable by admin"); - oracles[_oracle].pendingAdmin = _newAdmin; - - emit OracleAdminUpdateRequested(_oracle, msg.sender, _newAdmin); - } - - /** - * @notice accept the admin address transfer for an oracle - * @param _oracle is the address of the oracle whose admin is being transferred - */ - function acceptAdmin(address _oracle) - external - { - require(oracles[_oracle].pendingAdmin == msg.sender, "only callable by pending admin"); - oracles[_oracle].pendingAdmin = address(0); - oracles[_oracle].admin = msg.sender; - - emit OracleAdminUpdated(_oracle, msg.sender); - } - - /** - * @notice allows non-oracles to request a new round - */ - function requestNewRound() - external - returns (uint80) - { - require(requesters[msg.sender].authorized, "not authorized requester"); - - uint32 current = reportingRoundId; - require(rounds[current].updatedAt > 0 || timedOut(current), "prev round must be supersedable"); - - uint32 newRoundId = current.add(1); - requesterInitializeNewRound(newRoundId); - return newRoundId; - } - - /** - * @notice allows the owner to specify new non-oracles to start new rounds - * @param _requester is the address to set permissions for - * @param _authorized is a boolean specifying whether they can start new rounds or not - * @param _delay is the number of rounds the requester must wait before starting another round - */ - function setRequesterPermissions(address _requester, bool _authorized, uint32 _delay) - external - onlyOwner() - { - if (requesters[_requester].authorized == _authorized) return; - - if (_authorized) { - requesters[_requester].authorized = _authorized; - requesters[_requester].delay = _delay; - } else { - delete requesters[_requester]; - } - - emit RequesterPermissionsSet(_requester, _authorized, _delay); - } - - /** - * @notice called through LINK's transferAndCall to update available funds - * in the same transaction as the funds were transferred to the aggregator - * @param _data is mostly ignored. It is checked for length, to be sure - * nothing strange is passed in. - */ - function onTokenTransfer(address, uint256, bytes calldata _data) - external - { - require(_data.length == 0, "transfer doesn't accept calldata"); - updateAvailableFunds(); - } - - /** - * @notice a method to provide all current info oracles need. Intended only - * only to be callable by oracles. Not for use by contracts to read state. - * @param _oracle the address to look up information for. - */ - function oracleRoundState(address _oracle, uint32 _queriedRoundId) - external - view - returns ( - bool _eligibleToSubmit, - uint32 _roundId, - int256 _latestSubmission, - uint64 _startedAt, - uint64 _timeout, - uint128 _availableFunds, - uint8 _oracleCount, - uint128 _paymentAmount - ) - { - require(msg.sender == tx.origin, "off-chain reading only"); - - if (_queriedRoundId > 0) { - Round storage round = rounds[_queriedRoundId]; - RoundDetails storage details = details[_queriedRoundId]; - return ( - eligibleForSpecificRound(_oracle, _queriedRoundId), - _queriedRoundId, - oracles[_oracle].latestSubmission, - round.startedAt, - details.timeout, - recordedFunds.available, - oracleCount(), - (round.startedAt > 0 ? details.paymentAmount : paymentAmount) - ); - } else { - return oracleRoundStateSuggestRound(_oracle); - } - } - - /** - * @notice method to update the address which does external data validation. - * @param _newValidator designates the address of the new validation contract. - */ - function setValidator(address _newValidator) - public - onlyOwner() - { - address previous = address(validator); - - if (previous != _newValidator) { - validator = AggregatorValidatorInterface(_newValidator); - - emit ValidatorUpdated(previous, _newValidator); - } - } - - - /** - * Private - */ - - function initializeNewRound(uint32 _roundId) - private - { - updateTimedOutRoundInfo(_roundId.sub(1)); - - reportingRoundId = _roundId; - RoundDetails memory nextDetails = RoundDetails( - new int256[](0), - maxSubmissionCount, - minSubmissionCount, - timeout, - paymentAmount - ); - details[_roundId] = nextDetails; - rounds[_roundId].startedAt = uint64(block.timestamp); - - emit NewRound(_roundId, msg.sender, rounds[_roundId].startedAt); - } - - function oracleInitializeNewRound(uint32 _roundId) - private - { - if (!newRound(_roundId)) return; - uint256 lastStarted = oracles[msg.sender].lastStartedRound; // cache storage reads - if (_roundId <= lastStarted + restartDelay && lastStarted != 0) return; - - initializeNewRound(_roundId); - - oracles[msg.sender].lastStartedRound = _roundId; - } - - function requesterInitializeNewRound(uint32 _roundId) - private - { - if (!newRound(_roundId)) return; - uint256 lastStarted = requesters[msg.sender].lastStartedRound; // cache storage reads - require(_roundId > lastStarted + requesters[msg.sender].delay || lastStarted == 0, "must delay requests"); - - initializeNewRound(_roundId); - - requesters[msg.sender].lastStartedRound = _roundId; - } - - function updateTimedOutRoundInfo(uint32 _roundId) - private - { - if (!timedOut(_roundId)) return; - - uint32 prevId = _roundId.sub(1); - rounds[_roundId].answer = rounds[prevId].answer; - rounds[_roundId].answeredInRound = rounds[prevId].answeredInRound; - rounds[_roundId].updatedAt = uint64(block.timestamp); - - delete details[_roundId]; - } - - function eligibleForSpecificRound(address _oracle, uint32 _queriedRoundId) - private - view - returns (bool _eligible) - { - if (rounds[_queriedRoundId].startedAt > 0) { - return acceptingSubmissions(_queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0; - } else { - return delayed(_oracle, _queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0; - } - } - - function oracleRoundStateSuggestRound(address _oracle) - private - view - returns ( - bool _eligibleToSubmit, - uint32 _roundId, - int256 _latestSubmission, - uint64 _startedAt, - uint64 _timeout, - uint128 _availableFunds, - uint8 _oracleCount, - uint128 _paymentAmount - ) - { - Round storage round = rounds[0]; - OracleStatus storage oracle = oracles[_oracle]; - - bool shouldSupersede = oracle.lastReportedRound == reportingRoundId || !acceptingSubmissions(reportingRoundId); - // Instead of nudging oracles to submit to the next round, the inclusion of - // the shouldSupersede bool in the if condition pushes them towards - // submitting in a currently open round. - if (supersedable(reportingRoundId) && shouldSupersede) { - _roundId = reportingRoundId.add(1); - round = rounds[_roundId]; - - _paymentAmount = paymentAmount; - _eligibleToSubmit = delayed(_oracle, _roundId); - } else { - _roundId = reportingRoundId; - round = rounds[_roundId]; - - _paymentAmount = details[_roundId].paymentAmount; - _eligibleToSubmit = acceptingSubmissions(_roundId); - } - - if (validateOracleRound(_oracle, _roundId).length != 0) { - _eligibleToSubmit = false; - } - - return ( - _eligibleToSubmit, - _roundId, - oracle.latestSubmission, - round.startedAt, - details[_roundId].timeout, - recordedFunds.available, - oracleCount(), - _paymentAmount - ); - } - - function updateRoundAnswer(uint32 _roundId) - internal - returns (bool, int256) - { - if (details[_roundId].submissions.length < details[_roundId].minSubmissions) { - return (false, 0); - } - - int256 newAnswer = Median.calculateInplace(details[_roundId].submissions); - rounds[_roundId].answer = newAnswer; - rounds[_roundId].updatedAt = uint64(block.timestamp); - rounds[_roundId].answeredInRound = _roundId; - latestRoundId = _roundId; - - emit AnswerUpdated(newAnswer, _roundId, now); - - return (true, newAnswer); - } - - function validateAnswer( - uint32 _roundId, - int256 _newAnswer - ) - private - { - AggregatorValidatorInterface av = validator; // cache storage reads - if (address(av) == address(0)) return; - - uint32 prevRound = _roundId.sub(1); - uint32 prevAnswerRoundId = rounds[prevRound].answeredInRound; - int256 prevRoundAnswer = rounds[prevRound].answer; - // We do not want the validator to ever prevent reporting, so we limit its - // gas usage and catch any errors that may arise. - try av.validate{gas: VALIDATOR_GAS_LIMIT}( - prevAnswerRoundId, - prevRoundAnswer, - _roundId, - _newAnswer - ) {} catch {} - } - - function payOracle(uint32 _roundId) - private - { - uint128 payment = details[_roundId].paymentAmount; - Funds memory funds = recordedFunds; - funds.available = funds.available.sub(payment); - funds.allocated = funds.allocated.add(payment); - recordedFunds = funds; - oracles[msg.sender].withdrawable = oracles[msg.sender].withdrawable.add(payment); - - emit AvailableFundsUpdated(funds.available); - } - - function recordSubmission(int256 _submission, uint32 _roundId) - private - { - require(acceptingSubmissions(_roundId), "round not accepting submissions"); - - details[_roundId].submissions.push(_submission); - oracles[msg.sender].lastReportedRound = _roundId; - oracles[msg.sender].latestSubmission = _submission; - - emit SubmissionReceived(_submission, _roundId, msg.sender); - } - - function deleteRoundDetails(uint32 _roundId) - private - { - if (details[_roundId].submissions.length < details[_roundId].maxSubmissions) return; - - delete details[_roundId]; - } - - function timedOut(uint32 _roundId) - private - view - returns (bool) - { - uint64 startedAt = rounds[_roundId].startedAt; - uint32 roundTimeout = details[_roundId].timeout; - return startedAt > 0 && roundTimeout > 0 && startedAt.add(roundTimeout) < block.timestamp; - } - - function getStartingRound(address _oracle) - private - view - returns (uint32) - { - uint32 currentRound = reportingRoundId; - if (currentRound != 0 && currentRound == oracles[_oracle].endingRound) { - return currentRound; - } - return currentRound.add(1); - } - - function previousAndCurrentUnanswered(uint32 _roundId, uint32 _rrId) - private - view - returns (bool) - { - return _roundId.add(1) == _rrId && rounds[_rrId].updatedAt == 0; - } - - function requiredReserve(uint256 payment) - private - view - returns (uint256) - { - return payment.mul(oracleCount()).mul(RESERVE_ROUNDS); - } - - function addOracle( - address _oracle, - address _admin - ) - private - { - require(!oracleEnabled(_oracle), "oracle already enabled"); - - require(_admin != address(0), "cannot set admin to 0"); - require(oracles[_oracle].admin == address(0) || oracles[_oracle].admin == _admin, "owner cannot overwrite admin"); - - oracles[_oracle].startingRound = getStartingRound(_oracle); - oracles[_oracle].endingRound = ROUND_MAX; - oracles[_oracle].index = uint16(oracleAddresses.length); - oracleAddresses.push(_oracle); - oracles[_oracle].admin = _admin; - - emit OraclePermissionsUpdated(_oracle, true); - emit OracleAdminUpdated(_oracle, _admin); - } - - function removeOracle( - address _oracle - ) - private - { - require(oracleEnabled(_oracle), "oracle not enabled"); - - oracles[_oracle].endingRound = reportingRoundId.add(1); - address tail = oracleAddresses[uint256(oracleCount()).sub(1)]; - uint16 index = oracles[_oracle].index; - oracles[tail].index = index; - delete oracles[_oracle].index; - oracleAddresses[index] = tail; - oracleAddresses.pop(); - - emit OraclePermissionsUpdated(_oracle, false); - } - - function validateOracleRound(address _oracle, uint32 _roundId) - private - view - returns (bytes memory) - { - // cache storage reads - uint32 startingRound = oracles[_oracle].startingRound; - uint32 rrId = reportingRoundId; - - if (startingRound == 0) return "not enabled oracle"; - if (startingRound > _roundId) return "not yet enabled oracle"; - if (oracles[_oracle].endingRound < _roundId) return "no longer allowed oracle"; - if (oracles[_oracle].lastReportedRound >= _roundId) return "cannot report on previous rounds"; - if (_roundId != rrId && _roundId != rrId.add(1) && !previousAndCurrentUnanswered(_roundId, rrId)) return "invalid round to report"; - if (_roundId != 1 && !supersedable(_roundId.sub(1))) return "previous round not supersedable"; - } - - function supersedable(uint32 _roundId) - private - view - returns (bool) - { - return rounds[_roundId].updatedAt > 0 || timedOut(_roundId); - } - - function oracleEnabled(address _oracle) - private - view - returns (bool) - { - return oracles[_oracle].endingRound == ROUND_MAX; - } - - function acceptingSubmissions(uint32 _roundId) - private - view - returns (bool) - { - return details[_roundId].maxSubmissions != 0; - } - - function delayed(address _oracle, uint32 _roundId) - private - view - returns (bool) - { - uint256 lastStarted = oracles[_oracle].lastStartedRound; - return _roundId > lastStarted + restartDelay || lastStarted == 0; - } - - function newRound(uint32 _roundId) - private - view - returns (bool) - { - return _roundId == reportingRoundId.add(1); - } - - function validRoundId(uint256 _roundId) - private - pure - returns (bool) - { - return _roundId <= ROUND_MAX; - } - -} diff --git a/contracts/src/v0.6/KeeperBase.sol b/contracts/src/v0.6/KeeperBase.sol deleted file mode 100644 index ce9eccff196..00000000000 --- a/contracts/src/v0.6/KeeperBase.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -contract KeeperBase { - /** - * @notice method that allows it to be simulated via eth_call by checking that - * the sender is the zero address. - */ - function preventExecution() internal view { - require(tx.origin == address(0), "only for simulated backend"); - } - - /** - * @notice modifier that allows it to be simulated via eth_call by checking - * that the sender is the zero address. - */ - modifier cannotExecute() { - preventExecution(); - _; - } -} diff --git a/contracts/src/v0.6/KeeperCompatible.sol b/contracts/src/v0.6/KeeperCompatible.sol deleted file mode 100644 index 2a7ad60b0a0..00000000000 --- a/contracts/src/v0.6/KeeperCompatible.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./KeeperBase.sol"; -import "./interfaces/KeeperCompatibleInterface.sol"; - -abstract contract KeeperCompatible is KeeperBase, KeeperCompatibleInterface {} diff --git a/contracts/src/v0.6/LinkTokenReceiver.sol b/contracts/src/v0.6/LinkTokenReceiver.sol deleted file mode 100644 index 6009f6a5a61..00000000000 --- a/contracts/src/v0.6/LinkTokenReceiver.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -abstract contract LinkTokenReceiver { - - bytes4 constant private ORACLE_REQUEST_SELECTOR = 0x40429946; - uint256 constant private SELECTOR_LENGTH = 4; - uint256 constant private EXPECTED_REQUEST_WORDS = 2; - uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS); - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount` - * values to ensure correctness. Calls oracleRequest. - * @param _sender Address of the sender - * @param _amount Amount of LINK sent (specified in wei) - * @param _data Payload of the transaction - */ - function onTokenTransfer( - address _sender, - uint256 _amount, - bytes memory _data - ) - public - onlyLINK - validRequestLength(_data) - permittedFunctionsForLINK(_data) - { - assembly { - // solhint-disable-next-line avoid-low-level-calls - mstore(add(_data, 36), _sender) // ensure correct sender is passed - // solhint-disable-next-line avoid-low-level-calls - mstore(add(_data, 68), _amount) // ensure correct amount is passed - } - // solhint-disable-next-line avoid-low-level-calls - (bool success, ) = address(this).delegatecall(_data); // calls oracleRequest - require(success, "Unable to create request"); - } - - function getChainlinkToken() public view virtual returns (address); - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - require(msg.sender == getChainlinkToken(), "Must use LINK token"); - _; - } - - /** - * @dev Reverts if the given data does not begin with the `oracleRequest` function selector - * @param _data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory _data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(_data, 32)) - } - require(funcSelector == ORACLE_REQUEST_SELECTOR, "Must use whitelisted functions"); - _; - } - - /** - * @dev Reverts if the given payload is less than needed to create a request - * @param _data The request payload - */ - modifier validRequestLength(bytes memory _data) { - require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length"); - _; - } -} diff --git a/contracts/src/v0.6/Median.sol b/contracts/src/v0.6/Median.sol deleted file mode 100644 index d75b5b625ae..00000000000 --- a/contracts/src/v0.6/Median.sol +++ /dev/null @@ -1,248 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./vendor/SafeMathChainlink.sol"; -import "./SignedSafeMath.sol"; - -library Median { - using SignedSafeMath for int256; - - int256 constant INT_MAX = 2**255-1; - - /** - * @notice Returns the sorted middle, or the average of the two middle indexed items if the - * array has an even number of elements. - * @dev The list passed as an argument isn't modified. - * @dev This algorithm has expected runtime O(n), but for adversarially chosen inputs - * the runtime is O(n^2). - * @param list The list of elements to compare - */ - function calculate(int256[] memory list) - internal - pure - returns (int256) - { - return calculateInplace(copy(list)); - } - - /** - * @notice See documentation for function calculate. - * @dev The list passed as an argument may be permuted. - */ - function calculateInplace(int256[] memory list) - internal - pure - returns (int256) - { - require(0 < list.length, "list must not be empty"); - uint256 len = list.length; - uint256 middleIndex = len / 2; - if (len % 2 == 0) { - int256 median1; - int256 median2; - (median1, median2) = quickselectTwo(list, 0, len - 1, middleIndex - 1, middleIndex); - return SignedSafeMath.avg(median1, median2); - } else { - return quickselect(list, 0, len - 1, middleIndex); - } - } - - /** - * @notice Maximum length of list that shortSelectTwo can handle - */ - uint256 constant SHORTSELECTTWO_MAX_LENGTH = 7; - - /** - * @notice Select the k1-th and k2-th element from list of length at most 7 - * @dev Uses an optimal sorting network - */ - function shortSelectTwo( - int256[] memory list, - uint256 lo, - uint256 hi, - uint256 k1, - uint256 k2 - ) - private - pure - returns (int256 k1th, int256 k2th) - { - // Uses an optimal sorting network (https://en.wikipedia.org/wiki/Sorting_network) - // for lists of length 7. Network layout is taken from - // http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=7&algorithm=hibbard&output=svg - - uint256 len = hi + 1 - lo; - int256 x0 = list[lo + 0]; - int256 x1 = 1 < len ? list[lo + 1] : INT_MAX; - int256 x2 = 2 < len ? list[lo + 2] : INT_MAX; - int256 x3 = 3 < len ? list[lo + 3] : INT_MAX; - int256 x4 = 4 < len ? list[lo + 4] : INT_MAX; - int256 x5 = 5 < len ? list[lo + 5] : INT_MAX; - int256 x6 = 6 < len ? list[lo + 6] : INT_MAX; - - if (x0 > x1) {(x0, x1) = (x1, x0);} - if (x2 > x3) {(x2, x3) = (x3, x2);} - if (x4 > x5) {(x4, x5) = (x5, x4);} - if (x0 > x2) {(x0, x2) = (x2, x0);} - if (x1 > x3) {(x1, x3) = (x3, x1);} - if (x4 > x6) {(x4, x6) = (x6, x4);} - if (x1 > x2) {(x1, x2) = (x2, x1);} - if (x5 > x6) {(x5, x6) = (x6, x5);} - if (x0 > x4) {(x0, x4) = (x4, x0);} - if (x1 > x5) {(x1, x5) = (x5, x1);} - if (x2 > x6) {(x2, x6) = (x6, x2);} - if (x1 > x4) {(x1, x4) = (x4, x1);} - if (x3 > x6) {(x3, x6) = (x6, x3);} - if (x2 > x4) {(x2, x4) = (x4, x2);} - if (x3 > x5) {(x3, x5) = (x5, x3);} - if (x3 > x4) {(x3, x4) = (x4, x3);} - - uint256 index1 = k1 - lo; - if (index1 == 0) {k1th = x0;} - else if (index1 == 1) {k1th = x1;} - else if (index1 == 2) {k1th = x2;} - else if (index1 == 3) {k1th = x3;} - else if (index1 == 4) {k1th = x4;} - else if (index1 == 5) {k1th = x5;} - else if (index1 == 6) {k1th = x6;} - else {revert("k1 out of bounds");} - - uint256 index2 = k2 - lo; - if (k1 == k2) {return (k1th, k1th);} - else if (index2 == 0) {return (k1th, x0);} - else if (index2 == 1) {return (k1th, x1);} - else if (index2 == 2) {return (k1th, x2);} - else if (index2 == 3) {return (k1th, x3);} - else if (index2 == 4) {return (k1th, x4);} - else if (index2 == 5) {return (k1th, x5);} - else if (index2 == 6) {return (k1th, x6);} - else {revert("k2 out of bounds");} - } - - /** - * @notice Selects the k-th ranked element from list, looking only at indices between lo and hi - * (inclusive). Modifies list in-place. - */ - function quickselect(int256[] memory list, uint256 lo, uint256 hi, uint256 k) - private - pure - returns (int256 kth) - { - require(lo <= k); - require(k <= hi); - while (lo < hi) { - if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) { - int256 ignore; - (kth, ignore) = shortSelectTwo(list, lo, hi, k, k); - return kth; - } - uint256 pivotIndex = partition(list, lo, hi); - if (k <= pivotIndex) { - // since pivotIndex < (original hi passed to partition), - // termination is guaranteed in this case - hi = pivotIndex; - } else { - // since (original lo passed to partition) <= pivotIndex, - // termination is guaranteed in this case - lo = pivotIndex + 1; - } - } - return list[lo]; - } - - /** - * @notice Selects the k1-th and k2-th ranked elements from list, looking only at indices between - * lo and hi (inclusive). Modifies list in-place. - */ - function quickselectTwo( - int256[] memory list, - uint256 lo, - uint256 hi, - uint256 k1, - uint256 k2 - ) - internal // for testing - pure - returns (int256 k1th, int256 k2th) - { - require(k1 < k2); - require(lo <= k1 && k1 <= hi); - require(lo <= k2 && k2 <= hi); - - while (true) { - if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) { - return shortSelectTwo(list, lo, hi, k1, k2); - } - uint256 pivotIdx = partition(list, lo, hi); - if (k2 <= pivotIdx) { - hi = pivotIdx; - } else if (pivotIdx < k1) { - lo = pivotIdx + 1; - } else { - assert(k1 <= pivotIdx && pivotIdx < k2); - k1th = quickselect(list, lo, pivotIdx, k1); - k2th = quickselect(list, pivotIdx + 1, hi, k2); - return (k1th, k2th); - } - } - } - - /** - * @notice Partitions list in-place using Hoare's partitioning scheme. - * Only elements of list between indices lo and hi (inclusive) will be modified. - * Returns an index i, such that: - * - lo <= i < hi - * - forall j in [lo, i]. list[j] <= list[i] - * - forall j in [i, hi]. list[i] <= list[j] - */ - function partition(int256[] memory list, uint256 lo, uint256 hi) - private - pure - returns (uint256) - { - // We don't care about overflow of the addition, because it would require a list - // larger than any feasible computer's memory. - int256 pivot = list[(lo + hi) / 2]; - lo -= 1; // this can underflow. that's intentional. - hi += 1; - while (true) { - do { - lo += 1; - } while (list[lo] < pivot); - do { - hi -= 1; - } while (list[hi] > pivot); - if (lo < hi) { - (list[lo], list[hi]) = (list[hi], list[lo]); - } else { - // Let orig_lo and orig_hi be the original values of lo and hi passed to partition. - // Then, hi < orig_hi, because hi decreases *strictly* monotonically - // in each loop iteration and - // - either list[orig_hi] > pivot, in which case the first loop iteration - // will achieve hi < orig_hi; - // - or list[orig_hi] <= pivot, in which case at least two loop iterations are - // needed: - // - lo will have to stop at least once in the interval - // [orig_lo, (orig_lo + orig_hi)/2] - // - (orig_lo + orig_hi)/2 < orig_hi - return hi; - } - } - } - - /** - * @notice Makes an in-memory copy of the array passed in - * @param list Reference to the array to be copied - */ - function copy(int256[] memory list) - private - pure - returns(int256[] memory) - { - int256[] memory list2 = new int256[](list.length); - for (uint256 i = 0; i < list.length; i++) { - list2[i] = list[i]; - } - return list2; - } -} diff --git a/contracts/src/v0.6/Oracle.sol b/contracts/src/v0.6/Oracle.sol deleted file mode 100644 index 967114f7f87..00000000000 --- a/contracts/src/v0.6/Oracle.sol +++ /dev/null @@ -1,303 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./LinkTokenReceiver.sol"; -import "./interfaces/ChainlinkRequestInterface.sol"; -import "./interfaces/OracleInterface.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/WithdrawalInterface.sol"; -import "./vendor/Ownable.sol"; -import "./vendor/SafeMathChainlink.sol"; - -/** - * @title The Chainlink Oracle contract - * @notice Node operators can deploy this contract to fulfill requests sent to them - */ -contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable, LinkTokenReceiver, WithdrawalInterface { - using SafeMathChainlink for uint256; - - uint256 constant public EXPIRY_TIME = 5 minutes; - uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000; - // We initialize fields to 1 instead of 0 so that the first invocation - // does not cost more gas. - uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1; - - LinkTokenInterface internal LinkToken; - mapping(bytes32 => bytes32) private commitments; - mapping(address => bool) private authorizedNodes; - uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST; - - event OracleRequest( - bytes32 indexed specId, - address requester, - bytes32 requestId, - uint256 payment, - address callbackAddr, - bytes4 callbackFunctionId, - uint256 cancelExpiration, - uint256 dataVersion, - bytes data - ); - - event CancelOracleRequest( - bytes32 indexed requestId - ); - - /** - * @notice Deploy with the address of the LINK token - * @dev Sets the LinkToken address for the imported LinkTokenInterface - * @param _link The address of the LINK token - */ - constructor(address _link) - public - Ownable() - { - LinkToken = LinkTokenInterface(_link); // external but already deployed and unalterable - } - - /** - * @notice Creates the Chainlink request - * @dev Stores the hash of the params as the on-chain commitment for the request. - * Emits OracleRequest event for the Chainlink node to detect. - * @param _sender The sender of the request - * @param _payment The amount of payment given (specified in wei) - * @param _specId The Job Specification ID - * @param _callbackAddress The callback address for the response - * @param _callbackFunctionId The callback function ID for the response - * @param _nonce The nonce sent by the requester - * @param _dataVersion The specified data version - * @param _data The CBOR payload of the request - */ - function oracleRequest( - address _sender, - uint256 _payment, - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunctionId, - uint256 _nonce, - uint256 _dataVersion, - bytes calldata _data - ) - external - override - onlyLINK() - checkCallbackAddress(_callbackAddress) - { - bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce)); - require(commitments[requestId] == 0, "Must use a unique ID"); - // solhint-disable-next-line not-rely-on-time - uint256 expiration = now.add(EXPIRY_TIME); - - commitments[requestId] = keccak256( - abi.encodePacked( - _payment, - _callbackAddress, - _callbackFunctionId, - expiration - ) - ); - - emit OracleRequest( - _specId, - _sender, - requestId, - _payment, - _callbackAddress, - _callbackFunctionId, - expiration, - _dataVersion, - _data); - } - - /** - * @notice Called by the Chainlink node to fulfill requests - * @dev Given params must hash back to the commitment stored from `oracleRequest`. - * Will call the callback address' callback function without bubbling up error - * checking in a `require` so that the node can get paid. - * @param _requestId The fulfillment request ID that must match the requester's - * @param _payment The payment amount that will be released for the oracle (specified in wei) - * @param _callbackAddress The callback address to call for fulfillment - * @param _callbackFunctionId The callback function ID to use for fulfillment - * @param _expiration The expiration that the node should respond by before the requester can cancel - * @param _data The data to return to the consuming contract - * @return Status if the external call was successful - */ - function fulfillOracleRequest( - bytes32 _requestId, - uint256 _payment, - address _callbackAddress, - bytes4 _callbackFunctionId, - uint256 _expiration, - bytes32 _data - ) - external - onlyAuthorizedNode - override - isValidRequest(_requestId) - returns (bool) - { - bytes32 paramsHash = keccak256( - abi.encodePacked( - _payment, - _callbackAddress, - _callbackFunctionId, - _expiration - ) - ); - require(commitments[_requestId] == paramsHash, "Params do not match request ID"); - withdrawableTokens = withdrawableTokens.add(_payment); - delete commitments[_requestId]; - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = _callbackAddress.call(abi.encodeWithSelector(_callbackFunctionId, _requestId, _data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - /** - * @notice Use this to check if a node is authorized for fulfilling requests - * @param _node The address of the Chainlink node - * @return The authorization status of the node - */ - function getAuthorizationStatus(address _node) - external - view - override - returns (bool) - { - return authorizedNodes[_node]; - } - - /** - * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. - * @param _node The address of the Chainlink node - * @param _allowed Bool value to determine if the node can fulfill requests - */ - function setFulfillmentPermission(address _node, bool _allowed) - external - override - onlyOwner() - { - authorizedNodes[_node] = _allowed; - } - - /** - * @notice Allows the node operator to withdraw earned LINK to a given address - * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node - * @param _recipient The address to send the LINK token to - * @param _amount The amount to send (specified in wei) - */ - function withdraw(address _recipient, uint256 _amount) - external - override(OracleInterface, WithdrawalInterface) - onlyOwner - hasAvailableFunds(_amount) - { - withdrawableTokens = withdrawableTokens.sub(_amount); - assert(LinkToken.transfer(_recipient, _amount)); - } - - /** - * @notice Displays the amount of LINK that is available for the node operator to withdraw - * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage - * @return The amount of withdrawable LINK on the contract - */ - function withdrawable() - external - view - override(OracleInterface, WithdrawalInterface) - onlyOwner() - returns (uint256) - { - return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST); - } - - /** - * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK - * sent for the request back to the requester's address. - * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid - * Emits CancelOracleRequest event. - * @param _requestId The request ID - * @param _payment The amount of payment given (specified in wei) - * @param _callbackFunc The requester's specified callback address - * @param _expiration The time of the expiration for the request - */ - function cancelOracleRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunc, - uint256 _expiration - ) - external - override - { - bytes32 paramsHash = keccak256( - abi.encodePacked( - _payment, - msg.sender, - _callbackFunc, - _expiration) - ); - require(paramsHash == commitments[_requestId], "Params do not match request ID"); - // solhint-disable-next-line not-rely-on-time - require(_expiration <= now, "Request is not expired"); - - delete commitments[_requestId]; - emit CancelOracleRequest(_requestId); - - assert(LinkToken.transfer(msg.sender, _payment)); - } - - /** - * @notice Returns the address of the LINK token - * @dev This is the public implementation for chainlinkTokenAddress, which is - * an internal method of the ChainlinkClient contract - */ - function getChainlinkToken() - public - view - override - returns (address) - { - return address(LinkToken); - } - - // MODIFIERS - - /** - * @dev Reverts if amount requested is greater than withdrawable balance - * @param _amount The given amount to compare to `withdrawableTokens` - */ - modifier hasAvailableFunds(uint256 _amount) { - require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance"); - _; - } - - /** - * @dev Reverts if request ID does not exist - * @param _requestId The given request ID to check in stored `commitments` - */ - modifier isValidRequest(bytes32 _requestId) { - require(commitments[_requestId] != 0, "Must have a valid requestId"); - _; - } - - /** - * @dev Reverts if `msg.sender` is not authorized to fulfill requests - */ - modifier onlyAuthorizedNode() { - require(authorizedNodes[msg.sender] || msg.sender == owner(), "Not an authorized node to fulfill requests"); - _; - } - - /** - * @dev Reverts if the callback address is the LINK token - * @param _to The callback address - */ - modifier checkCallbackAddress(address _to) { - require(_to != address(LinkToken), "Cannot callback to LINK"); - _; - } - -} diff --git a/contracts/src/v0.6/Owned.sol b/contracts/src/v0.6/Owned.sol deleted file mode 100644 index 0dc7c4660b6..00000000000 --- a/contracts/src/v0.6/Owned.sol +++ /dev/null @@ -1,62 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >0.6.0 <0.8.0; - -/** - * @title The Owned contract - * @notice A contract with helpers for basic contract ownership. - */ -contract Owned { - - address public owner; - address private pendingOwner; - - event OwnershipTransferRequested( - address indexed from, - address indexed to - ); - event OwnershipTransferred( - address indexed from, - address indexed to - ); - - constructor() public { - owner = msg.sender; - } - - /** - * @dev Allows an owner to begin transferring ownership to a new address, - * pending. - */ - function transferOwnership(address _to) - external - onlyOwner() - { - pendingOwner = _to; - - emit OwnershipTransferRequested(owner, _to); - } - - /** - * @dev Allows an ownership transfer to be completed by the recipient. - */ - function acceptOwnership() - external - { - require(msg.sender == pendingOwner, "Must be proposed owner"); - - address oldOwner = owner; - owner = msg.sender; - pendingOwner = address(0); - - emit OwnershipTransferred(oldOwner, msg.sender); - } - - /** - * @dev Reverts if called by anyone other than the contract owner. - */ - modifier onlyOwner() { - require(msg.sender == owner, "Only callable by owner"); - _; - } - -} diff --git a/contracts/src/v0.6/SafeMath128.sol b/contracts/src/v0.6/SafeMath128.sol deleted file mode 100644 index c79665bcf87..00000000000 --- a/contracts/src/v0.6/SafeMath128.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - * - * This library is a version of Open Zeppelin's SafeMath, modified to support - * unsigned 128 bit integers. - */ -library SafeMath128 { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint128 a, uint128 b) internal pure returns (uint128) { - uint128 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint128 a, uint128 b) internal pure returns (uint128) { - require(b <= a, "SafeMath: subtraction overflow"); - uint128 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint128 a, uint128 b) internal pure returns (uint128) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint128 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint128 a, uint128 b) internal pure returns (uint128) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint128 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint128 a, uint128 b) internal pure returns (uint128) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.6/SafeMath32.sol b/contracts/src/v0.6/SafeMath32.sol deleted file mode 100644 index 21944bb0d80..00000000000 --- a/contracts/src/v0.6/SafeMath32.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - * - * This library is a version of Open Zeppelin's SafeMath, modified to support - * unsigned 32 bit integers. - */ -library SafeMath32 { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint32 a, uint32 b) internal pure returns (uint32) { - uint32 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint32 a, uint32 b) internal pure returns (uint32) { - require(b <= a, "SafeMath: subtraction overflow"); - uint32 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint32 a, uint32 b) internal pure returns (uint32) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint32 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint32 a, uint32 b) internal pure returns (uint32) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint32 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint32 a, uint32 b) internal pure returns (uint32) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.6/SafeMath64.sol b/contracts/src/v0.6/SafeMath64.sol deleted file mode 100644 index 2bb3b79121b..00000000000 --- a/contracts/src/v0.6/SafeMath64.sol +++ /dev/null @@ -1,111 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - * - * This library is a version of Open Zeppelin's SafeMath, modified to support - * unsigned 64 bit integers. - */ -library SafeMath64 { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint64 a, uint64 b) internal pure returns (uint64) { - uint64 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint64 a, uint64 b) internal pure returns (uint64) { - require(b <= a, "SafeMath: subtraction overflow"); - uint64 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint64 a, uint64 b) internal pure returns (uint64) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint64 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint64 a, uint64 b) internal pure returns (uint64) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint64 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint64 a, uint64 b) internal pure returns (uint64) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.6/SignedSafeMath.sol b/contracts/src/v0.6/SignedSafeMath.sol deleted file mode 100644 index 32941de704a..00000000000 --- a/contracts/src/v0.6/SignedSafeMath.sol +++ /dev/null @@ -1,75 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -library SignedSafeMath { - int256 constant private _INT256_MIN = -2**255; - - /** - * @dev Multiplies two signed integers, reverts on overflow. - */ - function mul(int256 a, int256 b) internal pure returns (int256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); - - int256 c = a * b; - require(c / a == b, "SignedSafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero. - */ - function div(int256 a, int256 b) internal pure returns (int256) { - require(b != 0, "SignedSafeMath: division by zero"); - require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); - - int256 c = a / b; - - return c; - } - - /** - * @dev Subtracts two signed integers, reverts on overflow. - */ - function sub(int256 a, int256 b) internal pure returns (int256) { - int256 c = a - b; - require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); - - return c; - } - - /** - * @dev Adds two signed integers, reverts on overflow. - */ - function add(int256 a, int256 b) internal pure returns (int256) { - int256 c = a + b; - require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); - - return c; - } - - /** - * @notice Computes average of two signed integers, ensuring that the computation - * doesn't overflow. - * @dev If the result is not an integer, it is rounded towards zero. For example, - * avg(-3, -4) = -3 - */ - function avg(int256 _a, int256 _b) - internal - pure - returns (int256) - { - if ((_a < 0 && _b > 0) || (_a > 0 && _b < 0)) { - return add(_a, _b) / 2; - } - int256 remainder = (_a % 2 + _b % 2) / 2; - return add(add(_a / 2, _b / 2), remainder); - } -} diff --git a/contracts/src/v0.6/SimpleReadAccessController.sol b/contracts/src/v0.6/SimpleReadAccessController.sol deleted file mode 100644 index fbd714a1c7b..00000000000 --- a/contracts/src/v0.6/SimpleReadAccessController.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./SimpleWriteAccessController.sol"; - -/** - * @title SimpleReadAccessController - * @notice Gives access to: - * - any externally owned account (note that off-chain actors can always read - * any contract storage regardless of on-chain access control measures, so this - * does not weaken the access control while improving usability) - * - accounts explicitly added to an access list - * @dev SimpleReadAccessController is not suitable for access controlling writes - * since it grants any externally owned account access! See - * SimpleWriteAccessController for that. - */ -contract SimpleReadAccessController is SimpleWriteAccessController { - - /** - * @notice Returns the access of an address - * @param _user The address to query - */ - function hasAccess( - address _user, - bytes memory _calldata - ) - public - view - virtual - override - returns (bool) - { - return super.hasAccess(_user, _calldata) || _user == tx.origin; - } - -} diff --git a/contracts/src/v0.6/SimpleWriteAccessController.sol b/contracts/src/v0.6/SimpleWriteAccessController.sol deleted file mode 100644 index 02a6db7b166..00000000000 --- a/contracts/src/v0.6/SimpleWriteAccessController.sol +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >0.6.0 <0.8.0; - -import "./Owned.sol"; -import "./interfaces/AccessControllerInterface.sol"; - -/** - * @title SimpleWriteAccessController - * @notice Gives access to accounts explicitly added to an access list by the - * controller's owner. - * @dev does not make any special permissions for externally, see - * SimpleReadAccessController for that. - */ -contract SimpleWriteAccessController is AccessControllerInterface, Owned { - - bool public checkEnabled; - mapping(address => bool) internal accessList; - - event AddedAccess(address user); - event RemovedAccess(address user); - event CheckAccessEnabled(); - event CheckAccessDisabled(); - - constructor() - public - { - checkEnabled = true; - } - - /** - * @notice Returns the access of an address - * @param _user The address to query - */ - function hasAccess( - address _user, - bytes memory - ) - public - view - virtual - override - returns (bool) - { - return accessList[_user] || !checkEnabled; - } - - /** - * @notice Adds an address to the access list - * @param _user The address to add - */ - function addAccess(address _user) - external - onlyOwner() - { - if (!accessList[_user]) { - accessList[_user] = true; - - emit AddedAccess(_user); - } - } - - /** - * @notice Removes an address from the access list - * @param _user The address to remove - */ - function removeAccess(address _user) - external - onlyOwner() - { - if (accessList[_user]) { - accessList[_user] = false; - - emit RemovedAccess(_user); - } - } - - /** - * @notice makes the access check enforced - */ - function enableAccessCheck() - external - onlyOwner() - { - if (!checkEnabled) { - checkEnabled = true; - - emit CheckAccessEnabled(); - } - } - - /** - * @notice makes the access check unenforced - */ - function disableAccessCheck() - external - onlyOwner() - { - if (checkEnabled) { - checkEnabled = false; - - emit CheckAccessDisabled(); - } - } - - /** - * @dev reverts if the caller does not have access - */ - modifier checkAccess() { - require(hasAccess(msg.sender, msg.data), "No access"); - _; - } -} diff --git a/contracts/src/v0.6/VRF.sol b/contracts/src/v0.6/VRF.sol deleted file mode 100644 index 9cbb145e3b8..00000000000 --- a/contracts/src/v0.6/VRF.sol +++ /dev/null @@ -1,533 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -/** **************************************************************************** - * @notice Verification of verifiable-random-function (VRF) proofs, following - * @notice https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @notice See https://eprint.iacr.org/2017/099.pdf for security proofs. - - * @dev Bibliographic references: - - * @dev Goldberg, et al., "Verifiable Random Functions (VRFs)", Internet Draft - * @dev draft-irtf-cfrg-vrf-05, IETF, Aug 11 2019, - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05 - - * @dev Papadopoulos, et al., "Making NSEC5 Practical for DNSSEC", Cryptology - * @dev ePrint Archive, Report 2017/099, https://eprint.iacr.org/2017/099.pdf - * **************************************************************************** - * @dev USAGE - - * @dev The main entry point is randomValueFromVRFProof. See its docstring. - * **************************************************************************** - * @dev PURPOSE - - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is computationally indistinguishable to her from a uniform - * @dev random sample from the output space. - - * @dev The purpose of this contract is to perform that verification. - * **************************************************************************** - * @dev DESIGN NOTES - - * @dev The VRF algorithm verified here satisfies the full unqiqueness, full - * @dev collision resistance, and full pseudorandomness security properties. - * @dev See "SECURITY PROPERTIES" below, and - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-3 - - * @dev An elliptic curve point is generally represented in the solidity code - * @dev as a uint256[2], corresponding to its affine coordinates in - * @dev GF(FIELD_SIZE). - - * @dev For the sake of efficiency, this implementation deviates from the spec - * @dev in some minor ways: - - * @dev - Keccak hash rather than the SHA256 hash recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev Keccak costs much less gas on the EVM, and provides similar security. - - * @dev - Secp256k1 curve instead of the P-256 or ED25519 curves recommended in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 - * @dev For curve-point multiplication, it's much cheaper to abuse ECRECOVER - - * @dev - hashToCurve recursively hashes until it finds a curve x-ordinate. On - * @dev the EVM, this is slightly more efficient than the recommendation in - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - * @dev step 5, to concatenate with a nonce then hash, and rehash with the - * @dev nonce updated until a valid x-ordinate is found. - - * @dev - hashToCurve does not include a cipher version string or the byte 0x1 - * @dev in the hash message, as recommended in step 5.B of the draft - * @dev standard. They are unnecessary here because no variation in the - * @dev cipher suite is allowed. - - * @dev - Similarly, the hash input in scalarFromCurvePoints does not include a - * @dev commitment to the cipher suite, either, which differs from step 2 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - * @dev . Also, the hash input is the concatenation of the uncompressed - * @dev points, not the compressed points as recommended in step 3. - - * @dev - In the calculation of the challenge value "c", the "u" value (i.e. - * @dev the value computed by Reggie as the nonce times the secp256k1 - * @dev generator point, see steps 5 and 7 of - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.3 - * @dev ) is replaced by its ethereum address, i.e. the lower 160 bits of the - * @dev keccak hash of the original u. This is because we only verify the - * @dev calculation of u up to its address, by abusing ECRECOVER. - * **************************************************************************** - * @dev SECURITY PROPERTIES - - * @dev Here are the security properties for this VRF: - - * @dev Full uniqueness: For any seed and valid VRF public key, there is - * @dev exactly one VRF output which can be proved to come from that seed, in - * @dev the sense that the proof will pass verifyVRFProof. - - * @dev Full collision resistance: It's cryptographically infeasible to find - * @dev two seeds with same VRF output from a fixed, valid VRF key - - * @dev Full pseudorandomness: Absent the proofs that the VRF outputs are - * @dev derived from a given seed, the outputs are computationally - * @dev indistinguishable from randomness. - - * @dev https://eprint.iacr.org/2017/099.pdf, Appendix B contains the proofs - * @dev for these properties. - - * @dev For secp256k1, the key validation described in section - * @dev https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.6 - * @dev is unnecessary, because secp256k1 has cofactor 1, and the - * @dev representation of the public key used here (affine x- and y-ordinates - * @dev of the secp256k1 point on the standard y^2=x^3+7 curve) cannot refer to - * @dev the point at infinity. - * **************************************************************************** - * @dev OTHER SECURITY CONSIDERATIONS - * - * @dev The seed input to the VRF could in principle force an arbitrary amount - * @dev of work in hashToCurve, by requiring extra rounds of hashing and - * @dev checking whether that's yielded the x ordinate of a secp256k1 point. - * @dev However, under the Random Oracle Model the probability of choosing a - * @dev point which forces n extra rounds in hashToCurve is 2⁻ⁿ. The base cost - * @dev for calling hashToCurve is about 25,000 gas, and each round of checking - * @dev for a valid x ordinate costs about 15,555 gas, so to find a seed for - * @dev which hashToCurve would cost more than 2,017,000 gas, one would have to - * @dev try, in expectation, about 2¹²⁸ seeds, which is infeasible for any - * @dev foreseeable computational resources. (25,000 + 128 * 15,555 < 2,017,000.) - - * @dev Since the gas block limit for the Ethereum main net is 10,000,000 gas, - * @dev this means it is infeasible for an adversary to prevent correct - * @dev operation of this contract by choosing an adverse seed. - - * @dev (See TestMeasureHashToCurveGasCost for verification of the gas cost for - * @dev hashToCurve.) - - * @dev It may be possible to make a secure constant-time hashToCurve function. - * @dev See notes in hashToCurve docstring. -*/ -contract VRF { - - // See https://www.secg.org/sec2-v2.pdf, section 2.4.1, for these constants. - uint256 constant private GROUP_ORDER = // Number of points in Secp256k1 - // solium-disable-next-line indentation - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141; - // Prime characteristic of the galois field over which Secp256k1 is defined - uint256 constant private FIELD_SIZE = - // solium-disable-next-line indentation - 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F; - uint256 constant private WORD_LENGTH_BYTES = 0x20; - - // (base^exponent) % FIELD_SIZE - // Cribbed from https://medium.com/@rbkhmrcr/precompiles-solidity-e5d29bd428c4 - function bigModExp(uint256 base, uint256 exponent) - internal view returns (uint256 exponentiation) { - uint256 callResult; - uint256[6] memory bigModExpContractInputs; - bigModExpContractInputs[0] = WORD_LENGTH_BYTES; // Length of base - bigModExpContractInputs[1] = WORD_LENGTH_BYTES; // Length of exponent - bigModExpContractInputs[2] = WORD_LENGTH_BYTES; // Length of modulus - bigModExpContractInputs[3] = base; - bigModExpContractInputs[4] = exponent; - bigModExpContractInputs[5] = FIELD_SIZE; - uint256[1] memory output; - assembly { // solhint-disable-line no-inline-assembly - callResult := staticcall( - not(0), // Gas cost: no limit - 0x05, // Bigmodexp contract address - bigModExpContractInputs, - 0xc0, // Length of input segment: 6*0x20-bytes - output, - 0x20 // Length of output segment - ) - } - if (callResult == 0) {revert("bigModExp failure!");} - return output[0]; - } - - // Let q=FIELD_SIZE. q % 4 = 3, ∴ x≡r^2 mod q ⇒ x^SQRT_POWER≡±r mod q. See - // https://en.wikipedia.org/wiki/Modular_square_root#Prime_or_prime_power_modulus - uint256 constant private SQRT_POWER = (FIELD_SIZE + 1) >> 2; - - // Computes a s.t. a^2 = x in the field. Assumes a exists - function squareRoot(uint256 x) internal view returns (uint256) { - return bigModExp(x, SQRT_POWER); - } - - // The value of y^2 given that (x,y) is on secp256k1. - function ySquared(uint256 x) internal pure returns (uint256) { - // Curve is y^2=x^3+7. See section 2.4.1 of https://www.secg.org/sec2-v2.pdf - uint256 xCubed = mulmod(x, mulmod(x, x, FIELD_SIZE), FIELD_SIZE); - return addmod(xCubed, 7, FIELD_SIZE); - } - - // True iff p is on secp256k1 - function isOnCurve(uint256[2] memory p) internal pure returns (bool) { - return ySquared(p[0]) == mulmod(p[1], p[1], FIELD_SIZE); - } - - // Hash x uniformly into {0, ..., FIELD_SIZE-1}. - function fieldHash(bytes memory b) internal pure returns (uint256 x_) { - x_ = uint256(keccak256(b)); - // Rejecting if x >= FIELD_SIZE corresponds to step 2.1 in section 2.3.4 of - // http://www.secg.org/sec1-v2.pdf , which is part of the definition of - // string_to_point in the IETF draft - while (x_ >= FIELD_SIZE) { - x_ = uint256(keccak256(abi.encodePacked(x_))); - } - } - - // Hash b to a random point which hopefully lies on secp256k1. The y ordinate - // is always even, due to - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.1.1 - // step 5.C, which references arbitrary_string_to_point, defined in - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.5 as - // returning the point with given x ordinate, and even y ordinate. - function newCandidateSecp256k1Point(bytes memory b) - internal view returns (uint256[2] memory p) { - p[0] = fieldHash(b); - p[1] = squareRoot(ySquared(p[0])); - if (p[1] % 2 == 1) { - p[1] = FIELD_SIZE - p[1]; - } - } - - // Domain-separation tag for initial hash in hashToCurve. Corresponds to - // vrf.go/hashToCurveHashPrefix - uint256 constant HASH_TO_CURVE_HASH_PREFIX = 1; - - // Cryptographic hash function onto the curve. - // - // Corresponds to algorithm in section 5.4.1.1 of the draft standard. (But see - // DESIGN NOTES above for slight differences.) - // - // TODO(alx): Implement a bounded-computation hash-to-curve, as described in - // "Construction of Rational Points on Elliptic Curves over Finite Fields" - // http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.831.5299&rep=rep1&type=pdf - // and suggested by - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-01#section-5.2.2 - // (Though we can't used exactly that because secp256k1's j-invariant is 0.) - // - // This would greatly simplify the analysis in "OTHER SECURITY CONSIDERATIONS" - // https://www.pivotaltracker.com/story/show/171120900 - function hashToCurve(uint256[2] memory pk, uint256 input) - internal view returns (uint256[2] memory rv) { - rv = newCandidateSecp256k1Point(abi.encodePacked(HASH_TO_CURVE_HASH_PREFIX, - pk, input)); - while (!isOnCurve(rv)) { - rv = newCandidateSecp256k1Point(abi.encodePacked(rv[0])); - } - } - - /** ********************************************************************* - * @notice Check that product==scalar*multiplicand - * - * @dev Based on Vitalik Buterin's idea in ethresear.ch post cited below. - * - * @param multiplicand: secp256k1 point - * @param scalar: non-zero GF(GROUP_ORDER) scalar - * @param product: secp256k1 expected to be multiplier * multiplicand - * @return verifies true iff product==scalar*multiplicand, with cryptographically high probability - */ - function ecmulVerify(uint256[2] memory multiplicand, uint256 scalar, - uint256[2] memory product) internal pure returns(bool verifies) - { - require(scalar != 0); // Rules out an ecrecover failure case - uint256 x = multiplicand[0]; // x ordinate of multiplicand - uint8 v = multiplicand[1] % 2 == 0 ? 27 : 28; // parity of y ordinate - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // Point corresponding to address ecrecover(0, v, x, s=scalar*x) is - // (x⁻¹ mod GROUP_ORDER) * (scalar * x * multiplicand - 0 * g), i.e. - // scalar*multiplicand. See https://crypto.stackexchange.com/a/18106 - bytes32 scalarTimesX = bytes32(mulmod(scalar, x, GROUP_ORDER)); - address actual = ecrecover(bytes32(0), v, bytes32(x), scalarTimesX); - // Explicit conversion to address takes bottom 160 bits - address expected = address(uint256(keccak256(abi.encodePacked(product)))); - return (actual == expected); - } - - // Returns x1/z1-x2/z2=(x1z2-x2z1)/(z1z2) in projective coordinates on P¹(𝔽ₙ) - function projectiveSub(uint256 x1, uint256 z1, uint256 x2, uint256 z2) - internal pure returns(uint256 x3, uint256 z3) { - uint256 num1 = mulmod(z2, x1, FIELD_SIZE); - uint256 num2 = mulmod(FIELD_SIZE - x2, z1, FIELD_SIZE); - (x3, z3) = (addmod(num1, num2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - } - - // Returns x1/z1*x2/z2=(x1x2)/(z1z2), in projective coordinates on P¹(𝔽ₙ) - function projectiveMul(uint256 x1, uint256 z1, uint256 x2, uint256 z2) - internal pure returns(uint256 x3, uint256 z3) { - (x3, z3) = (mulmod(x1, x2, FIELD_SIZE), mulmod(z1, z2, FIELD_SIZE)); - } - - /** ************************************************************************** - @notice Computes elliptic-curve sum, in projective co-ordinates - - @dev Using projective coordinates avoids costly divisions - - @dev To use this with p and q in affine coordinates, call - @dev projectiveECAdd(px, py, qx, qy). This will return - @dev the addition of (px, py, 1) and (qx, qy, 1), in the - @dev secp256k1 group. - - @dev This can be used to calculate the z which is the inverse to zInv - @dev in isValidVRFOutput. But consider using a faster - @dev re-implementation such as ProjectiveECAdd in the golang vrf package. - - @dev This function assumes [px,py,1],[qx,qy,1] are valid projective - coordinates of secp256k1 points. That is safe in this contract, - because this method is only used by linearCombination, which checks - points are on the curve via ecrecover. - ************************************************************************** - @param px The first affine coordinate of the first summand - @param py The second affine coordinate of the first summand - @param qx The first affine coordinate of the second summand - @param qy The second affine coordinate of the second summand - - (px,py) and (qx,qy) must be distinct, valid secp256k1 points. - ************************************************************************** - Return values are projective coordinates of [px,py,1]+[qx,qy,1] as points - on secp256k1, in P²(𝔽ₙ) - @return sx - @return sy - @return sz - */ - function projectiveECAdd(uint256 px, uint256 py, uint256 qx, uint256 qy) - internal pure returns(uint256 sx, uint256 sy, uint256 sz) { - // See "Group law for E/K : y^2 = x^3 + ax + b", in section 3.1.2, p. 80, - // "Guide to Elliptic Curve Cryptography" by Hankerson, Menezes and Vanstone - // We take the equations there for (sx,sy), and homogenize them to - // projective coordinates. That way, no inverses are required, here, and we - // only need the one inverse in affineECAdd. - - // We only need the "point addition" equations from Hankerson et al. Can - // skip the "point doubling" equations because p1 == p2 is cryptographically - // impossible, and require'd not to be the case in linearCombination. - - // Add extra "projective coordinate" to the two points - (uint256 z1, uint256 z2) = (1, 1); - - // (lx, lz) = (qy-py)/(qx-px), i.e., gradient of secant line. - uint256 lx = addmod(qy, FIELD_SIZE - py, FIELD_SIZE); - uint256 lz = addmod(qx, FIELD_SIZE - px, FIELD_SIZE); - - uint256 dx; // Accumulates denominator from sx calculation - // sx=((qy-py)/(qx-px))^2-px-qx - (sx, dx) = projectiveMul(lx, lz, lx, lz); // ((qy-py)/(qx-px))^2 - (sx, dx) = projectiveSub(sx, dx, px, z1); // ((qy-py)/(qx-px))^2-px - (sx, dx) = projectiveSub(sx, dx, qx, z2); // ((qy-py)/(qx-px))^2-px-qx - - uint256 dy; // Accumulates denominator from sy calculation - // sy=((qy-py)/(qx-px))(px-sx)-py - (sy, dy) = projectiveSub(px, z1, sx, dx); // px-sx - (sy, dy) = projectiveMul(sy, dy, lx, lz); // ((qy-py)/(qx-px))(px-sx) - (sy, dy) = projectiveSub(sy, dy, py, z1); // ((qy-py)/(qx-px))(px-sx)-py - - if (dx != dy) { // Cross-multiply to put everything over a common denominator - sx = mulmod(sx, dy, FIELD_SIZE); - sy = mulmod(sy, dx, FIELD_SIZE); - sz = mulmod(dx, dy, FIELD_SIZE); - } else { // Already over a common denominator, use that for z ordinate - sz = dx; - } - } - - // p1+p2, as affine points on secp256k1. - // - // invZ must be the inverse of the z returned by projectiveECAdd(p1, p2). - // It is computed off-chain to save gas. - // - // p1 and p2 must be distinct, because projectiveECAdd doesn't handle - // point doubling. - function affineECAdd( - uint256[2] memory p1, uint256[2] memory p2, - uint256 invZ) internal pure returns (uint256[2] memory) { - uint256 x; - uint256 y; - uint256 z; - (x, y, z) = projectiveECAdd(p1[0], p1[1], p2[0], p2[1]); - require(mulmod(z, invZ, FIELD_SIZE) == 1, "invZ must be inverse of z"); - // Clear the z ordinate of the projective representation by dividing through - // by it, to obtain the affine representation - return [mulmod(x, invZ, FIELD_SIZE), mulmod(y, invZ, FIELD_SIZE)]; - } - - // True iff address(c*p+s*g) == lcWitness, where g is generator. (With - // cryptographically high probability.) - function verifyLinearCombinationWithGenerator( - uint256 c, uint256[2] memory p, uint256 s, address lcWitness) - internal pure returns (bool) { - // Rule out ecrecover failure modes which return address 0. - require(lcWitness != address(0), "bad witness"); - uint8 v = (p[1] % 2 == 0) ? 27 : 28; // parity of y-ordinate of p - bytes32 pseudoHash = bytes32(GROUP_ORDER - mulmod(p[0], s, GROUP_ORDER)); // -s*p[0] - bytes32 pseudoSignature = bytes32(mulmod(c, p[0], GROUP_ORDER)); // c*p[0] - // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9 - // The point corresponding to the address returned by - // ecrecover(-s*p[0],v,p[0],c*p[0]) is - // (p[0]⁻¹ mod GROUP_ORDER)*(c*p[0]-(-s)*p[0]*g)=c*p+s*g. - // See https://crypto.stackexchange.com/a/18106 - // https://bitcoin.stackexchange.com/questions/38351/ecdsa-v-r-s-what-is-v - address computed = ecrecover(pseudoHash, v, bytes32(p[0]), pseudoSignature); - return computed == lcWitness; - } - - // c*p1 + s*p2. Requires cp1Witness=c*p1 and sp2Witness=s*p2. Also - // requires cp1Witness != sp2Witness (which is fine for this application, - // since it is cryptographically impossible for them to be equal. In the - // (cryptographically impossible) case that a prover accidentally derives - // a proof with equal c*p1 and s*p2, they should retry with a different - // proof nonce.) Assumes that all points are on secp256k1 - // (which is checked in verifyVRFProof below.) - function linearCombination( - uint256 c, uint256[2] memory p1, uint256[2] memory cp1Witness, - uint256 s, uint256[2] memory p2, uint256[2] memory sp2Witness, - uint256 zInv) - internal pure returns (uint256[2] memory) { - require((cp1Witness[0] - sp2Witness[0]) % FIELD_SIZE != 0, - "points in sum must be distinct"); - require(ecmulVerify(p1, c, cp1Witness), "First multiplication check failed"); - require(ecmulVerify(p2, s, sp2Witness), "Second multiplication check failed"); - return affineECAdd(cp1Witness, sp2Witness, zInv); - } - - // Domain-separation tag for the hash taken in scalarFromCurvePoints. - // Corresponds to scalarFromCurveHashPrefix in vrf.go - uint256 constant SCALAR_FROM_CURVE_POINTS_HASH_PREFIX = 2; - - // Pseudo-random number from inputs. Matches vrf.go/scalarFromCurvePoints, and - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-vrf-05#section-5.4.3 - // The draft calls (in step 7, via the definition of string_to_int, in - // https://datatracker.ietf.org/doc/html/rfc8017#section-4.2 ) for taking the - // first hash without checking that it corresponds to a number less than the - // group order, which will lead to a slight bias in the sample. - // - // TODO(alx): We could save a bit of gas by following the standard here and - // using the compressed representation of the points, if we collated the y - // parities into a single bytes32. - // https://www.pivotaltracker.com/story/show/171120588 - function scalarFromCurvePoints( - uint256[2] memory hash, uint256[2] memory pk, uint256[2] memory gamma, - address uWitness, uint256[2] memory v) - internal pure returns (uint256 s) { - return uint256( - keccak256(abi.encodePacked(SCALAR_FROM_CURVE_POINTS_HASH_PREFIX, - hash, pk, gamma, v, uWitness))); - } - - // True if (gamma, c, s) is a correctly constructed randomness proof from pk - // and seed. zInv must be the inverse of the third ordinate from - // projectiveECAdd applied to cGammaWitness and sHashWitness. Corresponds to - // section 5.3 of the IETF draft. - // - // TODO(alx): Since I'm only using pk in the ecrecover call, I could only pass - // the x ordinate, and the parity of the y ordinate in the top bit of uWitness - // (which I could make a uint256 without using any extra space.) Would save - // about 2000 gas. https://www.pivotaltracker.com/story/show/170828567 - function verifyVRFProof( - uint256[2] memory pk, uint256[2] memory gamma, uint256 c, uint256 s, - uint256 seed, address uWitness, uint256[2] memory cGammaWitness, - uint256[2] memory sHashWitness, uint256 zInv) - internal view { - require(isOnCurve(pk), "public key is not on curve"); - require(isOnCurve(gamma), "gamma is not on curve"); - require(isOnCurve(cGammaWitness), "cGammaWitness is not on curve"); - require(isOnCurve(sHashWitness), "sHashWitness is not on curve"); - // Step 5. of IETF draft section 5.3 (pk corresponds to 5.3's Y, and here - // we use the address of u instead of u itself. Also, here we add the - // terms instead of taking the difference, and in the proof consruction in - // vrf.GenerateProof, we correspondingly take the difference instead of - // taking the sum as they do in step 7 of section 5.1.) - require( - verifyLinearCombinationWithGenerator(c, pk, s, uWitness), - "addr(c*pk+s*g)≠_uWitness" - ); - // Step 4. of IETF draft section 5.3 (pk corresponds to Y, seed to alpha_string) - uint256[2] memory hash = hashToCurve(pk, seed); - // Step 6. of IETF draft section 5.3, but see note for step 5 about +/- terms - uint256[2] memory v = linearCombination( - c, gamma, cGammaWitness, s, hash, sHashWitness, zInv); - // Steps 7. and 8. of IETF draft section 5.3 - uint256 derivedC = scalarFromCurvePoints(hash, pk, gamma, uWitness, v); - require(c == derivedC, "invalid proof"); - } - - // Domain-separation tag for the hash used as the final VRF output. - // Corresponds to vrfRandomOutputHashPrefix in vrf.go - uint256 constant VRF_RANDOM_OUTPUT_HASH_PREFIX = 3; - - // Length of proof marshaled to bytes array. Shows layout of proof - uint public constant PROOF_LENGTH = 64 + // PublicKey (uncompressed format.) - 64 + // Gamma - 32 + // C - 32 + // S - 32 + // Seed - 0 + // Dummy entry: The following elements are included for gas efficiency: - 32 + // uWitness (gets padded to 256 bits, even though it's only 160) - 64 + // cGammaWitness - 64 + // sHashWitness - 32; // zInv (Leave Output out, because that can be efficiently calculated) - - /* *************************************************************************** - * @notice Returns proof's output, if proof is valid. Otherwise reverts - - * @param proof A binary-encoded proof, as output by vrf.Proof.MarshalForSolidityVerifier - * - * Throws if proof is invalid, otherwise: - * @return output i.e., the random output implied by the proof - * *************************************************************************** - * @dev See the calculation of PROOF_LENGTH for the binary layout of proof. - */ - function randomValueFromVRFProof(bytes memory proof) - internal view returns (uint256 output) { - require(proof.length == PROOF_LENGTH, "wrong proof length"); - - uint256[2] memory pk; // parse proof contents into these variables - uint256[2] memory gamma; - // c, s and seed combined (prevents "stack too deep" compilation error) - uint256[3] memory cSSeed; - address uWitness; - uint256[2] memory cGammaWitness; - uint256[2] memory sHashWitness; - uint256 zInv; - (pk, gamma, cSSeed, uWitness, cGammaWitness, sHashWitness, zInv) = abi.decode( - proof, (uint256[2], uint256[2], uint256[3], address, uint256[2], - uint256[2], uint256)); - verifyVRFProof( - pk, - gamma, - cSSeed[0], // c - cSSeed[1], // s - cSSeed[2], // seed - uWitness, - cGammaWitness, - sHashWitness, - zInv - ); - output = uint256(keccak256(abi.encode(VRF_RANDOM_OUTPUT_HASH_PREFIX, gamma))); - } -} diff --git a/contracts/src/v0.6/VRFConsumerBase.sol b/contracts/src/v0.6/VRFConsumerBase.sol deleted file mode 100644 index ca1c3811b3b..00000000000 --- a/contracts/src/v0.6/VRFConsumerBase.sol +++ /dev/null @@ -1,202 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./vendor/SafeMathChainlink.sol"; - -import "./interfaces/LinkTokenInterface.sol"; - -import "./VRFRequestIDBase.sol"; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBase, and can - * @dev initialize VRFConsumerBase's attributes in their constructor as - * @dev shown: - * - * @dev contract VRFConsumer { - * @dev constructor(, address _vrfCoordinator, address _link) - * @dev VRFConsumerBase(_vrfCoordinator, _link) public { - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash), and have told you the minimum LINK - * @dev price for VRF service. Make sure your contract has sufficient LINK, and - * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you - * @dev want to generate randomness from. - * - * @dev Once the VRFCoordinator has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomness method. - * - * @dev The randomness argument to fulfillRandomness is the actual random value - * @dev generated from your seed. - * - * @dev The requestId argument is generated from the keyHash and the seed by - * @dev makeRequestId(keyHash, seed). If your contract could have concurrent - * @dev requests open, you can use the requestId to track which seed is - * @dev associated with which randomness. See VRFRequestIDBase.sol for more - * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously.) - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. (Which is critical to making unpredictable randomness! See the - * @dev next section.) - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the ultimate input to the VRF is mixed with the block hash of the - * @dev block in which the request is made, user-provided seeds have no impact - * @dev on its economic security properties. They are only included for API - * @dev compatability with previous versions of this contract. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. - */ -abstract contract VRFConsumerBase is VRFRequestIDBase { - - using SafeMathChainlink for uint256; - - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBase expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomness the VRF output - */ - function fulfillRandomness(bytes32 requestId, uint256 randomness) - internal virtual; - - /** - * @dev In order to keep backwards compatibility we have kept the user - * seed field around. We remove the use of it because given that the blockhash - * enters later, it overrides whatever randomness the used seed provides. - * Given that it adds no security, and can easily lead to misunderstandings, - * we have removed it from usage and can now provide a simpler API. - */ - uint256 constant private USER_SEED_PLACEHOLDER = 0; - - /** - * @notice requestRandomness initiates a request for VRF output given _seed - * - * @dev The fulfillRandomness method receives the output, once it's provided - * @dev by the Oracle, and verified by the vrfCoordinator. - * - * @dev The _keyHash must already be registered with the VRFCoordinator, and - * @dev the _fee must exceed the fee specified during registration of the - * @dev _keyHash. - * - * @dev The _seed parameter is vestigial, and is kept only for API - * @dev compatibility with older versions. It can't *hurt* to mix in some of - * @dev your own randomness, here, but it's not necessary because the VRF - * @dev oracle will mix the hash of the block containing your request into the - * @dev VRF seed it ultimately uses. - * - * @param _keyHash ID of public key against which randomness is generated - * @param _fee The amount of LINK to send with the request - * - * @return requestId unique ID for this request - * - * @dev The returned requestId can be used to distinguish responses to - * @dev concurrent requests. It is passed as the first argument to - * @dev fulfillRandomness. - */ - function requestRandomness(bytes32 _keyHash, uint256 _fee) - internal returns (bytes32 requestId) - { - LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); - // This is the seed passed to VRFCoordinator. The oracle will mix this with - // the hash of the block containing this request to obtain the seed/input - // which is finally passed to the VRF cryptographic machinery. - uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); - // nonces[_keyHash] must stay in sync with - // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above - // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). - // This provides protection against the user repeating their input seed, - // which would result in a predictable/duplicate output, if multiple such - // requests appeared in the same block. - nonces[_keyHash] = nonces[_keyHash].add(1); - return makeRequestId(_keyHash, vRFSeed); - } - - LinkTokenInterface immutable internal LINK; - address immutable private vrfCoordinator; - - // Nonces for each VRF key from which randomness has been requested. - // - // Must stay in sync with VRFCoordinator[_keyHash][this] - mapping(bytes32 /* keyHash */ => uint256 /* nonce */) private nonces; - - /** - * @param _vrfCoordinator address of VRFCoordinator contract - * @param _link address of LINK token contract - * - * @dev https://docs.chain.link/docs/link-token-contracts - */ - constructor(address _vrfCoordinator, address _link) public { - vrfCoordinator = _vrfCoordinator; - LINK = LinkTokenInterface(_link); - } - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external { - require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); - fulfillRandomness(requestId, randomness); - } -} diff --git a/contracts/src/v0.6/VRFCoordinator.sol b/contracts/src/v0.6/VRFCoordinator.sol deleted file mode 100644 index 9d1bcaf052a..00000000000 --- a/contracts/src/v0.6/VRFCoordinator.sol +++ /dev/null @@ -1,307 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "./vendor/SafeMathChainlink.sol"; - -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/BlockHashStoreInterface.sol"; - -import "./vendor/Ownable.sol"; - -import "./VRF.sol"; -import "./VRFRequestIDBase.sol"; -import "./VRFConsumerBase.sol"; - -/** - * @title VRFCoordinator coordinates on-chain verifiable-randomness requests - * @title with off-chain responses - */ -contract VRFCoordinator is VRF, VRFRequestIDBase, Ownable { - - using SafeMathChainlink for uint256; - - LinkTokenInterface internal LINK; - BlockHashStoreInterface internal blockHashStore; - - constructor(address _link, address _blockHashStore) public { - LINK = LinkTokenInterface(_link); - blockHashStore = BlockHashStoreInterface(_blockHashStore); - } - - struct Callback { // Tracks an ongoing request - address callbackContract; // Requesting contract, which will receive response - // Amount of LINK paid at request time. Total LINK = 1e9 * 1e18 < 2^96, so - // this representation is adequate, and saves a word of storage when this - // field follows the 160-bit callbackContract address. - uint96 randomnessFee; - // Commitment to seed passed to oracle by this contract, and the number of - // the block in which the request appeared. This is the keccak256 of the - // concatenation of those values. Storing this commitment saves a word of - // storage. - bytes32 seedAndBlockNum; - } - - struct ServiceAgreement { // Tracks oracle commitments to VRF service - address vRFOracle; // Oracle committing to respond with VRF service - uint96 fee; // Minimum payment for oracle response. Total LINK=1e9*1e18<2^96 - bytes32 jobID; // ID of corresponding chainlink job in oracle's DB - } - - mapping(bytes32 /* (provingKey, seed) */ => Callback) public callbacks; - mapping(bytes32 /* provingKey */ => ServiceAgreement) - public serviceAgreements; - mapping(address /* oracle */ => uint256 /* LINK balance */) - public withdrawableTokens; - mapping(bytes32 /* provingKey */ => mapping(address /* consumer */ => uint256)) - private nonces; - - // The oracle only needs the jobID to look up the VRF, but specifying public - // key as well prevents a malicious oracle from inducing VRF outputs from - // another oracle by reusing the jobID. - event RandomnessRequest( - bytes32 keyHash, - uint256 seed, - bytes32 indexed jobID, - address sender, - uint256 fee, - bytes32 requestID); - - event NewServiceAgreement(bytes32 keyHash, uint256 fee); - - event RandomnessRequestFulfilled(bytes32 requestId, uint256 output); - - /** - * @notice Commits calling address to serve randomness - * @param _fee minimum LINK payment required to serve randomness - * @param _oracle the address of the Chainlink node with the proving key and job - * @param _publicProvingKey public key used to prove randomness - * @param _jobID ID of the corresponding chainlink job in the oracle's db - */ - function registerProvingKey( - uint256 _fee, address _oracle, uint256[2] calldata _publicProvingKey, bytes32 _jobID - ) - external - onlyOwner() - { - bytes32 keyHash = hashOfKey(_publicProvingKey); - address oldVRFOracle = serviceAgreements[keyHash].vRFOracle; - require(oldVRFOracle == address(0), "please register a new key"); - require(_oracle != address(0), "_oracle must not be 0x0"); - serviceAgreements[keyHash].vRFOracle = _oracle; - serviceAgreements[keyHash].jobID = _jobID; - // Yes, this revert message doesn't fit in a word - require(_fee <= 1e9 ether, - "you can't charge more than all the LINK in the world, greedy"); - serviceAgreements[keyHash].fee = uint96(_fee); - emit NewServiceAgreement(keyHash, _fee); - } - - /** - * @notice Called by LINK.transferAndCall, on successful LINK transfer - * - * @dev To invoke this, use the requestRandomness method in VRFConsumerBase. - * - * @dev The VRFCoordinator will call back to the calling contract when the - * @dev oracle responds, on the method fulfillRandomness. See - * @dev VRFConsumerBase.fulfilRandomness for its signature. Your consuming - * @dev contract should inherit from VRFConsumerBase, and implement - * @dev fulfilRandomness. - * - * @param _sender address: who sent the LINK (must be a contract) - * @param _fee amount of LINK sent - * @param _data abi-encoded call to randomnessRequest - */ - function onTokenTransfer(address _sender, uint256 _fee, bytes memory _data) - public - onlyLINK - { - (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); - randomnessRequest(keyHash, seed, _fee, _sender); - } - - /** - * @notice creates the chainlink request for randomness - * - * @param _keyHash ID of the VRF public key against which to generate output - * @param _consumerSeed Input to the VRF, from which randomness is generated - * @param _feePaid Amount of LINK sent with request. Must exceed fee for key - * @param _sender Requesting contract; to be called back with VRF output - * - * @dev _consumerSeed is mixed with key hash, sender address and nonce to - * @dev obtain preSeed, which is passed to VRF oracle, which mixes it with the - * @dev hash of the block containing this request, to compute the final seed. - * - * @dev The requestId used to store the request data is constructed from the - * @dev preSeed and keyHash. - */ - function randomnessRequest( - bytes32 _keyHash, - uint256 _consumerSeed, - uint256 _feePaid, - address _sender - ) - internal - sufficientLINK(_feePaid, _keyHash) - { - uint256 nonce = nonces[_keyHash][_sender]; - uint256 preSeed = makeVRFInputSeed(_keyHash, _consumerSeed, _sender, nonce); - bytes32 requestId = makeRequestId(_keyHash, preSeed); - // Cryptographically guaranteed by preSeed including an increasing nonce - assert(callbacks[requestId].callbackContract == address(0)); - callbacks[requestId].callbackContract = _sender; - assert(_feePaid < 1e27); // Total LINK fits in uint96 - callbacks[requestId].randomnessFee = uint96(_feePaid); - callbacks[requestId].seedAndBlockNum = keccak256(abi.encodePacked( - preSeed, block.number)); - emit RandomnessRequest(_keyHash, preSeed, serviceAgreements[_keyHash].jobID, - _sender, _feePaid, requestId); - nonces[_keyHash][_sender] = nonces[_keyHash][_sender].add(1); - } - - // Offsets into fulfillRandomnessRequest's _proof of various values - // - // Public key. Skips byte array's length prefix. - uint256 public constant PUBLIC_KEY_OFFSET = 0x20; - // Seed is 7th word in proof, plus word for length, (6+1)*0x20=0xe0 - uint256 public constant PRESEED_OFFSET = 0xe0; - - /** - * @notice Called by the chainlink node to fulfill requests - * - * @param _proof the proof of randomness. Actual random output built from this - * - * @dev The structure of _proof corresponds to vrf.MarshaledOnChainResponse, - * @dev in the node source code. I.e., it is a vrf.MarshaledProof with the - * @dev seed replaced by the preSeed, followed by the hash of the requesting - * @dev block. - */ - function fulfillRandomnessRequest(bytes memory _proof) public { - (bytes32 currentKeyHash, Callback memory callback, bytes32 requestId, - uint256 randomness) = getRandomnessFromProof(_proof); - - // Pay oracle - address oadd = serviceAgreements[currentKeyHash].vRFOracle; - withdrawableTokens[oadd] = withdrawableTokens[oadd].add( - callback.randomnessFee); - - // Forget request. Must precede callback (prevents reentrancy) - delete callbacks[requestId]; - callBackWithRandomness(requestId, randomness, callback.callbackContract); - - emit RandomnessRequestFulfilled(requestId, randomness); - } - - function callBackWithRandomness(bytes32 requestId, uint256 randomness, - address consumerContract) internal { - // Dummy variable; allows access to method selector in next line. See - // https://github.com/ethereum/solidity/issues/3506#issuecomment-553727797 - VRFConsumerBase v; - bytes memory resp = abi.encodeWithSelector( - v.rawFulfillRandomness.selector, requestId, randomness); - // The bound b here comes from https://eips.ethereum.org/EIPS/eip-150. The - // actual gas available to the consuming contract will be b-floor(b/64). - // This is chosen to leave the consuming contract ~200k gas, after the cost - // of the call itself. - uint256 b = 206000; - require(gasleft() >= b, "not enough gas for consumer"); - // A low-level call is necessary, here, because we don't want the consuming - // contract to be able to revert this execution, and thus deny the oracle - // payment for a valid randomness response. This also necessitates the above - // check on the gasleft, as otherwise there would be no indication if the - // callback method ran out of gas. - // - // solhint-disable-next-line avoid-low-level-calls - (bool success,) = consumerContract.call(resp); - // Avoid unused-local-variable warning. (success is only present to prevent - // a warning that the return value of consumerContract.call is unused.) - (success); - } - - function getRandomnessFromProof(bytes memory _proof) - internal view returns (bytes32 currentKeyHash, Callback memory callback, - bytes32 requestId, uint256 randomness) { - // blockNum follows proof, which follows length word (only direct-number - // constants are allowed in assembly, so have to compute this in code) - uint256 BLOCKNUM_OFFSET = 0x20 + PROOF_LENGTH; - // _proof.length skips the initial length word, so not including the - // blocknum in this length check balances out. - require(_proof.length == BLOCKNUM_OFFSET, "wrong proof length"); - uint256[2] memory publicKey; - uint256 preSeed; - uint256 blockNum; - assembly { // solhint-disable-line no-inline-assembly - publicKey := add(_proof, PUBLIC_KEY_OFFSET) - preSeed := mload(add(_proof, PRESEED_OFFSET)) - blockNum := mload(add(_proof, BLOCKNUM_OFFSET)) - } - currentKeyHash = hashOfKey(publicKey); - requestId = makeRequestId(currentKeyHash, preSeed); - callback = callbacks[requestId]; - require(callback.callbackContract != address(0), "no corresponding request"); - require(callback.seedAndBlockNum == keccak256(abi.encodePacked(preSeed, - blockNum)), "wrong preSeed or block num"); - - bytes32 blockHash = blockhash(blockNum); - if (blockHash == bytes32(0)) { - blockHash = blockHashStore.getBlockhash(blockNum); - require(blockHash != bytes32(0), "please prove blockhash"); - } - // The seed actually used by the VRF machinery, mixing in the blockhash - uint256 actualSeed = uint256(keccak256(abi.encodePacked(preSeed, blockHash))); - // solhint-disable-next-line no-inline-assembly - assembly { // Construct the actual proof from the remains of _proof - mstore(add(_proof, PRESEED_OFFSET), actualSeed) - mstore(_proof, PROOF_LENGTH) - } - randomness = VRF.randomValueFromVRFProof(_proof); // Reverts on failure - } - - /** - * @dev Allows the oracle operator to withdraw their LINK - * @param _recipient is the address the funds will be sent to - * @param _amount is the amount of LINK transferred from the Coordinator contract - */ - function withdraw(address _recipient, uint256 _amount) - external - hasAvailableFunds(_amount) - { - withdrawableTokens[msg.sender] = withdrawableTokens[msg.sender].sub(_amount); - assert(LINK.transfer(_recipient, _amount)); - } - - /** - * @notice Returns the serviceAgreements key associated with this public key - * @param _publicKey the key to return the address for - */ - function hashOfKey(uint256[2] memory _publicKey) public pure returns (bytes32) { - return keccak256(abi.encodePacked(_publicKey)); - } - - /** - * @dev Reverts if amount is not at least what was agreed upon in the service agreement - * @param _feePaid The payment for the request - * @param _keyHash The key which the request is for - */ - modifier sufficientLINK(uint256 _feePaid, bytes32 _keyHash) { - require(_feePaid >= serviceAgreements[_keyHash].fee, "Below agreed payment"); - _; - } - -/** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - require(msg.sender == address(LINK), "Must use LINK token"); - _; - } - - /** - * @dev Reverts if amount requested is greater than withdrawable balance - * @param _amount The given amount to compare to `withdrawableTokens` - */ - modifier hasAvailableFunds(uint256 _amount) { - require(withdrawableTokens[msg.sender] >= _amount, "can't withdraw more than balance"); - _; - } - -} diff --git a/contracts/src/v0.6/VRFRequestIDBase.sol b/contracts/src/v0.6/VRFRequestIDBase.sol deleted file mode 100644 index 2668ead3200..00000000000 --- a/contracts/src/v0.6/VRFRequestIDBase.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -contract VRFRequestIDBase { - - /** - * @notice returns the seed which is actually input to the VRF coordinator - * - * @dev To prevent repetition of VRF output due to repetition of the - * @dev user-supplied seed, that seed is combined in a hash with the - * @dev user-specific nonce, and the address of the consuming contract. The - * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in - * @dev the final seed, but the nonce does protect against repetition in - * @dev requests which are included in a single block. - * - * @param _userSeed VRF seed input provided by user - * @param _requester Address of the requesting contract - * @param _nonce User-specific nonce at the time of the request - */ - function makeVRFInputSeed(bytes32 _keyHash, uint256 _userSeed, - address _requester, uint256 _nonce) - internal pure returns (uint256) - { - return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); - } - - /** - * @notice Returns the id for this request - * @param _keyHash The serviceAgreement ID to be used for this request - * @param _vRFInputSeed The seed to be passed directly to the VRF - * @return The id for this request - * - * @dev Note that _vRFInputSeed is not the seed passed by the consuming - * @dev contract, but the one generated by makeVRFInputSeed - */ - function makeRequestId( - bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); - } -} diff --git a/contracts/src/v0.6/examples/VRFD20.sol b/contracts/src/v0.6/examples/VRFD20.sol deleted file mode 100644 index 0e4c041759c..00000000000 --- a/contracts/src/v0.6/examples/VRFD20.sol +++ /dev/null @@ -1,172 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../VRFConsumerBase.sol"; -import "../Owned.sol"; - -/** - * @notice A Chainlink VRF consumer which uses randomness to mimic the rolling - * of a 20 sided die - * @dev This is only an example implementation and not necessarily suitable for mainnet. - */ -contract VRFD20 is VRFConsumerBase, Owned { - using SafeMathChainlink for uint256; - - uint256 private constant ROLL_IN_PROGRESS = 42; - - bytes32 private s_keyHash; - uint256 private s_fee; - mapping(bytes32 => address) private s_rollers; - mapping(address => uint256) private s_results; - - event DiceRolled(bytes32 indexed requestId, address indexed roller); - event DiceLanded(bytes32 indexed requestId, uint256 indexed result); - - /** - * @notice Constructor inherits VRFConsumerBase - * - * @dev NETWORK: KOVAN - * @dev Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9 - * @dev LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088 - * @dev Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4 - * @dev Fee: 0.1 LINK (100000000000000000) - * - * @param vrfCoordinator address of the VRF Coordinator - * @param link address of the LINK token - * @param keyHash bytes32 representing the hash of the VRF job - * @param fee uint256 fee to pay the VRF oracle - */ - constructor(address vrfCoordinator, address link, bytes32 keyHash, uint256 fee) - public - VRFConsumerBase(vrfCoordinator, link) - { - s_keyHash = keyHash; - s_fee = fee; - } - - /** - * @notice Requests randomness from a user-provided seed - * @dev Warning: if the VRF response is delayed, avoid calling requestRandomness repeatedly - * as that would give miners/VRF operators latitude about which VRF response arrives first. - * @dev You must review your implementation details with extreme care. - * - * @param roller address of the roller - */ - function rollDice(address roller) public onlyOwner returns (bytes32 requestId) { - require(LINK.balanceOf(address(this)) >= s_fee, "Not enough LINK to pay fee"); - require(s_results[roller] == 0, "Already rolled"); - requestId = requestRandomness(s_keyHash, s_fee); - s_rollers[requestId] = roller; - s_results[roller] = ROLL_IN_PROGRESS; - emit DiceRolled(requestId, roller); - } - - /** - * @notice Callback function used by VRF Coordinator to return the random number - * to this contract. - * @dev Some action on the contract state should be taken here, like storing the result. - * @dev WARNING: take care to avoid having multiple VRF requests in flight if their order of arrival would result - * in contract states with different outcomes. Otherwise miners or the VRF operator would could take advantage - * by controlling the order. - * @dev The VRF Coordinator will only send this function verified responses, and the parent VRFConsumerBase - * contract ensures that this method only receives randomness from the designated VRFCoordinator. - * - * @param requestId bytes32 - * @param randomness The random result returned by the oracle - */ - function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { - uint256 d20Value = randomness.mod(20).add(1); - s_results[s_rollers[requestId]] = d20Value; - emit DiceLanded(requestId, d20Value); - } - - /** - * @notice Get the house assigned to the player once the address has rolled - * @param player address - * @return house as a string - */ - function house(address player) public view returns (string memory) { - require(s_results[player] != 0, "Dice not rolled"); - require(s_results[player] != ROLL_IN_PROGRESS, "Roll in progress"); - return getHouseName(s_results[player]); - } - - /** - * @notice Withdraw LINK from this contract. - * @dev this is an example only, and in a real contract withdrawals should - * happen according to the established withdrawal pattern: - * https://docs.soliditylang.org/en/v0.4.24/common-patterns.html#withdrawal-from-contracts - * @param to the address to withdraw LINK to - * @param value the amount of LINK to withdraw - */ - function withdrawLINK(address to, uint256 value) public onlyOwner { - require(LINK.transfer(to, value), "Not enough LINK"); - } - - /** - * @notice Set the key hash for the oracle - * - * @param keyHash bytes32 - */ - function setKeyHash(bytes32 keyHash) public onlyOwner { - s_keyHash = keyHash; - } - - /** - * @notice Get the current key hash - * - * @return bytes32 - */ - function keyHash() public view returns (bytes32) { - return s_keyHash; - } - - /** - * @notice Set the oracle fee for requesting randomness - * - * @param fee uint256 - */ - function setFee(uint256 fee) public onlyOwner { - s_fee = fee; - } - - /** - * @notice Get the current fee - * - * @return uint256 - */ - function fee() public view returns (uint256) { - return s_fee; - } - - /** - * @notice Get the house name from the id - * @param id uint256 - * @return house name string - */ - function getHouseName(uint256 id) private pure returns (string memory) { - string[20] memory houseNames = [ - "Targaryen", - "Lannister", - "Stark", - "Tyrell", - "Baratheon", - "Martell", - "Tully", - "Bolton", - "Greyjoy", - "Arryn", - "Frey", - "Mormont", - "Tarley", - "Dayne", - "Umber", - "Valeryon", - "Manderly", - "Clegane", - "Glover", - "Karstark" - ]; - return houseNames[id.sub(1)]; - } -} diff --git a/contracts/src/v0.6/interfaces/AccessControllerInterface.sol b/contracts/src/v0.6/interfaces/AccessControllerInterface.sol deleted file mode 100644 index 4bf48bb2aee..00000000000 --- a/contracts/src/v0.6/interfaces/AccessControllerInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >0.6.0 <0.8.0; - -interface AccessControllerInterface { - function hasAccess(address user, bytes calldata data) external view returns (bool); -} diff --git a/contracts/src/v0.6/interfaces/AggregatorInterface.sol b/contracts/src/v0.6/interfaces/AggregatorInterface.sol deleted file mode 100644 index 4f48160b4ac..00000000000 --- a/contracts/src/v0.6/interfaces/AggregatorInterface.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface AggregatorInterface { - function latestAnswer() - external - view - returns ( - int256 - ); - - function latestTimestamp() - external - view - returns ( - uint256 - ); - - function latestRound() - external - view - returns ( - uint256 - ); - - function getAnswer( - uint256 roundId - ) - external - view - returns ( - int256 - ); - - function getTimestamp( - uint256 roundId - ) - external - view - returns ( - uint256 - ); - - event AnswerUpdated( - int256 indexed current, - uint256 indexed roundId, - uint256 updatedAt - ); - - event NewRound( - uint256 indexed roundId, - address indexed startedBy, - uint256 startedAt - ); -} diff --git a/contracts/src/v0.6/interfaces/AggregatorV2V3Interface.sol b/contracts/src/v0.6/interfaces/AggregatorV2V3Interface.sol deleted file mode 100644 index 6b4975edf47..00000000000 --- a/contracts/src/v0.6/interfaces/AggregatorV2V3Interface.sol +++ /dev/null @@ -1,9 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./AggregatorInterface.sol"; -import "./AggregatorV3Interface.sol"; - -interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface -{ -} diff --git a/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol b/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol deleted file mode 100644 index a1af9924ca4..00000000000 --- a/contracts/src/v0.6/interfaces/AggregatorV3Interface.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface AggregatorV3Interface { - - function decimals() - external - view - returns ( - uint8 - ); - - function description() - external - view - returns ( - string memory - ); - - function version() - external - view - returns ( - uint256 - ); - - function getRoundData( - uint80 _roundId - ) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function latestRoundData() - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - -} diff --git a/contracts/src/v0.6/interfaces/AggregatorValidatorInterface.sol b/contracts/src/v0.6/interfaces/AggregatorValidatorInterface.sol deleted file mode 100644 index 50c3226f6d8..00000000000 --- a/contracts/src/v0.6/interfaces/AggregatorValidatorInterface.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface AggregatorValidatorInterface { - function validate( - uint256 previousRoundId, - int256 previousAnswer, - uint256 currentRoundId, - int256 currentAnswer - ) external returns (bool); -} diff --git a/contracts/src/v0.6/interfaces/BlockHashStoreInterface.sol b/contracts/src/v0.6/interfaces/BlockHashStoreInterface.sol deleted file mode 100644 index 18927e64eed..00000000000 --- a/contracts/src/v0.6/interfaces/BlockHashStoreInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -interface BlockHashStoreInterface { - function getBlockhash(uint256 number) external view returns (bytes32); -} diff --git a/contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol b/contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol deleted file mode 100644 index bcbd2511901..00000000000 --- a/contracts/src/v0.6/interfaces/ChainlinkRequestInterface.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface ChainlinkRequestInterface { - function oracleRequest( - address sender, - uint256 requestPrice, - bytes32 serviceAgreementID, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunctionId, - uint256 expiration - ) external; -} diff --git a/contracts/src/v0.6/interfaces/ENSInterface.sol b/contracts/src/v0.6/interfaces/ENSInterface.sol deleted file mode 100644 index 158242cd0d5..00000000000 --- a/contracts/src/v0.6/interfaces/ENSInterface.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface ENSInterface { - - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed node, address owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed node, address resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed node, uint64 ttl); - - - function setSubnodeOwner(bytes32 node, bytes32 label, address _owner) external; - function setResolver(bytes32 node, address _resolver) external; - function setOwner(bytes32 node, address _owner) external; - function setTTL(bytes32 node, uint64 _ttl) external; - function owner(bytes32 node) external view returns (address); - function resolver(bytes32 node) external view returns (address); - function ttl(bytes32 node) external view returns (uint64); - -} diff --git a/contracts/src/v0.6/interfaces/FeedRegistryInterface.sol b/contracts/src/v0.6/interfaces/FeedRegistryInterface.sol deleted file mode 100644 index 0eb2d1d6bd8..00000000000 --- a/contracts/src/v0.6/interfaces/FeedRegistryInterface.sol +++ /dev/null @@ -1,298 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; -pragma experimental ABIEncoderV2; - -import "./AggregatorV2V3Interface.sol"; - -interface FeedRegistryInterface { - struct Phase { - uint16 phaseId; - uint80 startingAggregatorRoundId; - uint80 endingAggregatorRoundId; - } - - event FeedProposed( - address indexed asset, - address indexed denomination, - address indexed proposedAggregator, - address currentAggregator, - address sender - ); - event FeedConfirmed( - address indexed asset, - address indexed denomination, - address indexed latestAggregator, - address previousAggregator, - uint16 nextPhaseId, - address sender - ); - - // V3 AggregatorV3Interface - - function decimals( - address base, - address quote - ) - external - view - returns ( - uint8 - ); - - function description( - address base, - address quote - ) - external - view - returns ( - string memory - ); - - function version( - address base, - address quote - ) - external - view - returns ( - uint256 - ); - - function latestRoundData( - address base, - address quote - ) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function getRoundData( - address base, - address quote, - uint80 _roundId - ) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - // V2 AggregatorInterface - - function latestAnswer( - address base, - address quote - ) - external - view - returns ( - int256 answer - ); - - function latestTimestamp( - address base, - address quote - ) - external - view - returns ( - uint256 timestamp - ); - - function latestRound( - address base, - address quote - ) - external - view - returns ( - uint256 roundId - ); - - function getAnswer( - address base, - address quote, - uint256 roundId - ) - external - view - returns ( - int256 answer - ); - - function getTimestamp( - address base, - address quote, - uint256 roundId - ) - external - view - returns ( - uint256 timestamp - ); - - // Registry getters - - function getFeed( - address base, - address quote - ) - external - view - returns ( - AggregatorV2V3Interface aggregator - ); - - function getPhaseFeed( - address base, - address quote, - uint16 phaseId - ) - external - view - returns ( - AggregatorV2V3Interface aggregator - ); - - function isFeedEnabled( - address aggregator - ) - external - view - returns ( - bool - ); - - function getPhase( - address base, - address quote, - uint16 phaseId - ) - external - view - returns ( - Phase memory phase - ); - - // Round helpers - - function getRoundFeed( - address base, - address quote, - uint80 roundId - ) - external - view - returns ( - AggregatorV2V3Interface aggregator - ); - - function getPhaseRange( - address base, - address quote, - uint16 phaseId - ) - external - view - returns ( - uint80 startingRoundId, - uint80 endingRoundId - ); - - function getPreviousRoundId( - address base, - address quote, - uint80 roundId - ) external - view - returns ( - uint80 previousRoundId - ); - - function getNextRoundId( - address base, - address quote, - uint80 roundId - ) external - view - returns ( - uint80 nextRoundId - ); - - // Feed management - - function proposeFeed( - address base, - address quote, - address aggregator - ) external; - - function confirmFeed( - address base, - address quote, - address aggregator - ) external; - - // Proposed aggregator - - function getProposedFeed( - address base, - address quote - ) - external - view - returns ( - AggregatorV2V3Interface proposedAggregator - ); - - function proposedGetRoundData( - address base, - address quote, - uint80 roundId - ) - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function proposedLatestRoundData( - address base, - address quote - ) - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - // Phases - function getCurrentPhaseId( - address base, - address quote - ) - external - view - returns ( - uint16 currentPhaseId - ); -} diff --git a/contracts/src/v0.6/interfaces/FlagsInterface.sol b/contracts/src/v0.6/interfaces/FlagsInterface.sol deleted file mode 100644 index ad39cae3a62..00000000000 --- a/contracts/src/v0.6/interfaces/FlagsInterface.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface FlagsInterface { - function getFlag(address) external view returns (bool); - function getFlags(address[] calldata) external view returns (bool[] memory); - function raiseFlag(address) external; - function raiseFlags(address[] calldata) external; - function lowerFlags(address[] calldata) external; - function setRaisingAccessController(address) external; -} diff --git a/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol b/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol deleted file mode 100644 index f092fc9ef40..00000000000 --- a/contracts/src/v0.6/interfaces/KeeperCompatibleInterface.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface KeeperCompatibleInterface { - - /** - * @notice method that is simulated by the keepers to see if any work actually - * needs to be performed. This method does does not actually need to be - * executable, and since it is only ever simulated it can consume lots of gas. - * @dev To ensure that it is never called, you may want to add the - * cannotExecute modifier from KeeperBase to your implementation of this - * method. - * @param checkData specified in the upkeep registration so it is always the - * same for a registered upkeep. This can easily be broken down into specific - * arguments using `abi.decode`, so multiple upkeeps can be registered on the - * same contract and easily differentiated by the contract. - * @return upkeepNeeded boolean to indicate whether the keeper should call - * performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try - * `abi.encode`. - */ - function checkUpkeep( - bytes calldata checkData - ) - external - returns ( - bool upkeepNeeded, - bytes memory performData - ); - - /** - * @notice method that is actually executed by the keepers, via the registry. - * The data returned by the checkUpkeep simulation will be passed into - * this method to actually be executed. - * @dev The input to this method should not be trusted, and the caller of the - * method should not even be restricted to any single registry. Anyone should - * be able call it, and the input should be validated, there is no guarantee - * that the data passed in is the performData returned from checkUpkeep. This - * could happen due to malicious keepers, racing keepers, or simply a state - * change while the performUpkeep transaction is waiting for confirmation. - * Always validate the data passed in. - * @param performData is the data which was passed back from the checkData - * simulation. If it is encoded, it can easily be decoded into other types by - * calling `abi.decode`. This data should not be trusted, and should be - * validated against the contract's current state. - */ - function performUpkeep( - bytes calldata performData - ) external; -} diff --git a/contracts/src/v0.6/interfaces/LinkTokenInterface.sol b/contracts/src/v0.6/interfaces/LinkTokenInterface.sol deleted file mode 100644 index eeb944411f7..00000000000 --- a/contracts/src/v0.6/interfaces/LinkTokenInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface LinkTokenInterface { - function allowance(address owner, address spender) external view returns (uint256 remaining); - function approve(address spender, uint256 value) external returns (bool success); - function balanceOf(address owner) external view returns (uint256 balance); - function decimals() external view returns (uint8 decimalPlaces); - function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); - function increaseApproval(address spender, uint256 subtractedValue) external; - function name() external view returns (string memory tokenName); - function symbol() external view returns (string memory tokenSymbol); - function totalSupply() external view returns (uint256 totalTokensIssued); - function transfer(address to, uint256 value) external returns (bool success); - function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success); - function transferFrom(address from, address to, uint256 value) external returns (bool success); -} diff --git a/contracts/src/v0.6/interfaces/OracleInterface.sol b/contracts/src/v0.6/interfaces/OracleInterface.sol deleted file mode 100644 index 96b49f0341d..00000000000 --- a/contracts/src/v0.6/interfaces/OracleInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface OracleInterface { - function fulfillOracleRequest( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes32 data - ) external returns (bool); - function getAuthorizationStatus(address node) external view returns (bool); - function setFulfillmentPermission(address node, bool allowed) external; - function withdraw(address recipient, uint256 amount) external; - function withdrawable() external view returns (uint256); -} diff --git a/contracts/src/v0.6/interfaces/PointerInterface.sol b/contracts/src/v0.6/interfaces/PointerInterface.sol deleted file mode 100644 index e1cac19dfea..00000000000 --- a/contracts/src/v0.6/interfaces/PointerInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface PointerInterface { - function getAddress() external view returns (address); -} diff --git a/contracts/src/v0.6/interfaces/WithdrawalInterface.sol b/contracts/src/v0.6/interfaces/WithdrawalInterface.sol deleted file mode 100644 index e83d3273fe8..00000000000 --- a/contracts/src/v0.6/interfaces/WithdrawalInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -interface WithdrawalInterface { - /** - * @notice transfer LINK held by the contract belonging to msg.sender to - * another address - * @param recipient is the address to send the LINK to - * @param amount is the amount of LINK to send - */ - function withdraw(address recipient, uint256 amount) external; - - /** - * @notice query the available amount of LINK to withdraw by msg.sender - */ - function withdrawable() external view returns (uint256); -} diff --git a/contracts/src/v0.6/tests/AggregatorValidatorMock.sol b/contracts/src/v0.6/tests/AggregatorValidatorMock.sol deleted file mode 100644 index 7af4717c688..00000000000 --- a/contracts/src/v0.6/tests/AggregatorValidatorMock.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../interfaces/AggregatorValidatorInterface.sol"; - -contract AggregatorValidatorMock is AggregatorValidatorInterface { - uint256 public previousRoundId; - int256 public previousAnswer; - uint256 public currentRoundId; - int256 public currentAnswer; - - event Validated( - uint256 _previousRoundId, - int256 indexed _previousAnswer, - uint256 _currentRoundId, - int256 indexed _currentAnswer - ); - - function validate( - uint256 _previousRoundId, - int256 _previousAnswer, - uint256 _currentRoundId, - int256 _currentAnswer - ) - external - override - returns (bool) - { - emit Validated( - _previousRoundId, - _previousAnswer, - _currentRoundId, - _currentAnswer - ); - return true; - } - -} diff --git a/contracts/src/v0.6/tests/BasicConsumer.sol b/contracts/src/v0.6/tests/BasicConsumer.sol deleted file mode 100644 index f657fb0bdc5..00000000000 --- a/contracts/src/v0.6/tests/BasicConsumer.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./Consumer.sol"; - -contract BasicConsumer is Consumer { - - constructor(address _link, address _oracle, bytes32 _specId) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - specId = _specId; - } - -} diff --git a/contracts/src/v0.6/tests/BlockhashStoreTestHelper.sol b/contracts/src/v0.6/tests/BlockhashStoreTestHelper.sol deleted file mode 100644 index 895962547da..00000000000 --- a/contracts/src/v0.6/tests/BlockhashStoreTestHelper.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../BlockhashStore.sol"; - -contract BlockhashStoreTestHelper is BlockhashStore { - function godmodeSetHash(uint256 n, bytes32 h) public { - s_blockhashes[n] = h; - } -} diff --git a/contracts/src/v0.6/tests/ChainlinkClientTestHelper.sol b/contracts/src/v0.6/tests/ChainlinkClientTestHelper.sol deleted file mode 100644 index 2a390dc56c0..00000000000 --- a/contracts/src/v0.6/tests/ChainlinkClientTestHelper.sol +++ /dev/null @@ -1,120 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../ChainlinkClient.sol"; -import "../vendor/SafeMathChainlink.sol"; - -contract ChainlinkClientTestHelper is ChainlinkClient { - using SafeMathChainlink for uint256; - - constructor( - address _link, - address _oracle - ) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - } - - event Request( - bytes32 id, - address callbackAddress, - bytes4 callbackfunctionSelector, - bytes data - ); - event LinkAmount( - uint256 amount - ); - - function publicNewRequest( - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature - ) - public - { - Chainlink.Request memory req = buildChainlinkRequest( - _id, _address, bytes4(keccak256(_fulfillmentSignature))); - emit Request( - req.id, - req.callbackAddress, - req.callbackFunctionId, - req.buf.buf - ); - } - - function publicRequest( - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) - public - { - Chainlink.Request memory req = buildChainlinkRequest( - _id, _address, bytes4(keccak256(_fulfillmentSignature))); - sendChainlinkRequest(req, _wei); - } - - function publicRequestRunTo( - address _oracle, - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) - public - { - Chainlink.Request memory run = buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - sendChainlinkRequestTo(_oracle, run, _wei); - } - - function publicCancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function publicChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); - } - - function publicFulfillChainlinkRequest(bytes32 _requestId, bytes32) public { - fulfillRequest(_requestId, bytes32(0)); - } - - function fulfillRequest(bytes32 _requestId, bytes32) - public - { - validateChainlinkCallback(_requestId); - } - - function publicLINK( - uint256 _amount - ) - public - { - emit LinkAmount(LINK.mul(_amount)); - } - - function publicOracleAddress() - public - view - returns ( - address - ) - { - return chainlinkOracleAddress(); - } - - function publicAddExternalRequest( - address _oracle, - bytes32 _requestId - ) - public - { - addChainlinkExternalRequest(_oracle, _requestId); - } -} diff --git a/contracts/src/v0.6/tests/ChainlinkTestHelper.sol b/contracts/src/v0.6/tests/ChainlinkTestHelper.sol deleted file mode 100644 index 09b46a97657..00000000000 --- a/contracts/src/v0.6/tests/ChainlinkTestHelper.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../Chainlink.sol"; -import "../vendor/CBORChainlink.sol"; -import "../vendor/BufferChainlink.sol"; - -contract ChainlinkTestHelper { - using Chainlink for Chainlink.Request; - using CBORChainlink for BufferChainlink.buffer; - - Chainlink.Request private req; - - event RequestData(bytes payload); - - function closeEvent() public { - emit RequestData(req.buf.buf); - } - - function setBuffer(bytes memory data) public { - Chainlink.Request memory r2 = req; - r2.setBuffer(data); - req = r2; - } - - function add(string memory _key, string memory _value) public { - Chainlink.Request memory r2 = req; - r2.add(_key, _value); - req = r2; - } - - function addBytes(string memory _key, bytes memory _value) public { - Chainlink.Request memory r2 = req; - r2.addBytes(_key, _value); - req = r2; - } - - function addInt(string memory _key, int256 _value) public { - Chainlink.Request memory r2 = req; - r2.addInt(_key, _value); - req = r2; - } - - function addUint(string memory _key, uint256 _value) public { - Chainlink.Request memory r2 = req; - r2.addUint(_key, _value); - req = r2; - } - - // Temporarily have method receive bytes32[] memory until experimental - // string[] memory can be invoked from truffle tests. - function addStringArray(string memory _key, bytes32[] memory _values) public { - string[] memory strings = new string[](_values.length); - for (uint256 i = 0; i < _values.length; i++) { - strings[i] = bytes32ToString(_values[i]); - } - Chainlink.Request memory r2 = req; - r2.addStringArray(_key, strings); - req = r2; - } - - function bytes32ToString(bytes32 x) private pure returns (string memory) { - bytes memory bytesString = new bytes(32); - uint charCount = 0; - for (uint j = 0; j < 32; j++) { - byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); - if (char != 0) { - bytesString[charCount] = char; - charCount++; - } - } - bytes memory bytesStringTrimmed = new bytes(charCount); - for (uint j = 0; j < charCount; j++) { - bytesStringTrimmed[j] = bytesString[j]; - } - return string(bytesStringTrimmed); - } -} diff --git a/contracts/src/v0.6/tests/CheckedMathTestHelper.sol b/contracts/src/v0.6/tests/CheckedMathTestHelper.sol deleted file mode 100644 index 1306c53d8e4..00000000000 --- a/contracts/src/v0.6/tests/CheckedMathTestHelper.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../CheckedMath.sol"; - -contract CheckedMathTestHelper { - using CheckedMath for int256; - - function add(int256 a, int256 b) - external - pure - returns (int256 result, bool ok) - { - return a.add(b); - } - - function sub(int256 a, int256 b) - external - pure - returns (int256 result, bool ok) - { - return a.sub(b); - } - - function mul(int256 a, int256 b) - external - pure - returns (int256 result, bool ok) - { - return a.mul(b); - } - - function div(int256 a, int256 b) - external - pure - returns (int256 result, bool ok) - { - return a.div(b); - } - -} diff --git a/contracts/src/v0.6/tests/ConcreteSignedSafeMath.sol b/contracts/src/v0.6/tests/ConcreteSignedSafeMath.sol deleted file mode 100644 index 14be54685b5..00000000000 --- a/contracts/src/v0.6/tests/ConcreteSignedSafeMath.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../SignedSafeMath.sol"; - -contract ConcreteSignedSafeMath { - function testAdd(int256 _a, int256 _b) - external - pure - returns (int256) - { - return SignedSafeMath.add(_a, _b); - } - - function testAvg(int256 _a, int256 _b) - external - pure - returns (int256) - { - return SignedSafeMath.avg(_a, _b); - } -} diff --git a/contracts/src/v0.6/tests/EmptyOracle.sol b/contracts/src/v0.6/tests/EmptyOracle.sol deleted file mode 100644 index f076d129926..00000000000 --- a/contracts/src/v0.6/tests/EmptyOracle.sol +++ /dev/null @@ -1,20 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../interfaces/ChainlinkRequestInterface.sol"; -import "../interfaces/OracleInterface.sol"; - -/* solhint-disable no-empty-blocks */ - -contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { - - function cancelOracleRequest(bytes32, uint256, bytes4, uint256) external override {} - function fulfillOracleRequest(bytes32, uint256, address, bytes4, uint256, bytes32) external override returns (bool) {} - function getAuthorizationStatus(address) external override view returns (bool) { return false; } - function onTokenTransfer(address, uint256, bytes calldata) external pure {} - function oracleRequest(address, uint256, bytes32, address, bytes4, uint256, uint256, bytes calldata) external override {} - function setFulfillmentPermission(address, bool) external override {} - function withdraw(address, uint256) external override {} - function withdrawable() external override view returns (uint256) {} - -} diff --git a/contracts/src/v0.6/tests/FlagsTestHelper.sol b/contracts/src/v0.6/tests/FlagsTestHelper.sol deleted file mode 100644 index 0ed37b6e965..00000000000 --- a/contracts/src/v0.6/tests/FlagsTestHelper.sol +++ /dev/null @@ -1,37 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../Flags.sol"; - -contract FlagsTestHelper { - Flags public flags; - - constructor( - address flagsContract - ) - public - { - flags = Flags(flagsContract); - } - - function getFlag( - address subject - ) - external - view - returns(bool) - { - return flags.getFlag(subject); - } - - function getFlags( - address[] calldata subjects - ) - external - view - returns(bool[] memory) - { - return flags.getFlags(subjects); - } - -} diff --git a/contracts/src/v0.6/tests/FluxAggregatorTestHelper.sol b/contracts/src/v0.6/tests/FluxAggregatorTestHelper.sol deleted file mode 100644 index 24af37f4992..00000000000 --- a/contracts/src/v0.6/tests/FluxAggregatorTestHelper.sol +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../FluxAggregator.sol"; - -contract FluxAggregatorTestHelper { - - uint80 public requestedRoundId; - - function readOracleRoundState(address _aggregator, address _oracle) - external - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - FluxAggregator(_aggregator).oracleRoundState(_oracle, 0); - } - - function readGetRoundData(address _aggregator, uint80 _roundID) - external - { - FluxAggregator(_aggregator).getRoundData(_roundID); - } - - function readLatestRoundData(address _aggregator) - external - { - FluxAggregator(_aggregator).latestRoundData(); - } - - function readLatestAnswer(address _aggregator) - external - { - FluxAggregator(_aggregator).latestAnswer(); - } - - function readLatestTimestamp(address _aggregator) - external - { - FluxAggregator(_aggregator).latestTimestamp(); - } - - function readLatestRound(address _aggregator) - external - { - FluxAggregator(_aggregator).latestRound(); - } - - function requestNewRound(address _aggregator) - external - { - requestedRoundId = FluxAggregator(_aggregator).requestNewRound(); - } - - function readGetAnswer(address _aggregator, uint256 _roundID) - external - { - FluxAggregator(_aggregator).getAnswer(_roundID); - } - - function readGetTimestamp(address _aggregator, uint256 _roundID) - external - { - FluxAggregator(_aggregator).getTimestamp(_roundID); - } - -} diff --git a/contracts/src/v0.6/tests/GasGuzzler.sol b/contracts/src/v0.6/tests/GasGuzzler.sol deleted file mode 100644 index 5b30f1bef52..00000000000 --- a/contracts/src/v0.6/tests/GasGuzzler.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -contract GasGuzzler { - fallback() external payable { - while (true) { - } - } -} - diff --git a/contracts/src/v0.6/tests/GasGuzzlingConsumer.sol b/contracts/src/v0.6/tests/GasGuzzlingConsumer.sol deleted file mode 100644 index 8122f45dbab..00000000000 --- a/contracts/src/v0.6/tests/GasGuzzlingConsumer.sol +++ /dev/null @@ -1,47 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "./Consumer.sol"; - -contract GasGuzzlingConsumer is Consumer{ - - constructor(address _link, address _oracle, bytes32 _specId) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - specId = _specId; - } - - function gassyRequestEthereumPrice(uint256 _payment) public { - Chainlink.Request memory req = buildChainlinkRequest(specId, address(this), this.gassyFulfill.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = "USD"; - req.addStringArray("path", path); - sendChainlinkRequest(req, _payment); - } - - function gassyFulfill(bytes32 _requestId, bytes32 _price) - public - recordChainlinkFulfillment(_requestId) - { - while(true){ - } - } - - function gassyMultiWordRequest(uint256 _payment) public { - Chainlink.Request memory req = buildChainlinkRequest(specId, address(this), this.gassyMultiWordFulfill.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = "USD"; - req.addStringArray("path", path); - sendChainlinkRequest(req, _payment); - } - - function gassyMultiWordFulfill(bytes32 _requestId, bytes memory _price) - public - recordChainlinkFulfillment(_requestId) - { - while(true){ - } - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/tests/KeeperCompatibleTestHelper.sol b/contracts/src/v0.6/tests/KeeperCompatibleTestHelper.sol deleted file mode 100644 index 5c760bfaeff..00000000000 --- a/contracts/src/v0.6/tests/KeeperCompatibleTestHelper.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../KeeperCompatible.sol"; - -contract KeeperCompatibleTestHelper is KeeperCompatible { - function checkUpkeep(bytes calldata) external override returns (bool, bytes memory) {} - - function performUpkeep(bytes calldata) external override {} - - function verifyCannotExecute() public view cannotExecute {} -} diff --git a/contracts/src/v0.6/tests/MedianTestHelper.sol b/contracts/src/v0.6/tests/MedianTestHelper.sol deleted file mode 100644 index 5386790f02f..00000000000 --- a/contracts/src/v0.6/tests/MedianTestHelper.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../Median.sol"; - -contract MedianTestHelper { - function publicGet(int256[] memory list) - public - pure - returns (int256) - { - return Median.calculate(list); - } - - function publicQuickselectTwo(int256[] memory list, uint256 k1, uint256 k2) - public - pure - returns (int256, int256) - { - return Median.quickselectTwo(list, 0, list.length - 1, k1, k2); - } -} diff --git a/contracts/src/v0.6/tests/MockETHLINKAggregator.sol b/contracts/src/v0.6/tests/MockETHLINKAggregator.sol deleted file mode 100644 index 70cd9a76bfd..00000000000 --- a/contracts/src/v0.6/tests/MockETHLINKAggregator.sol +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../interfaces/AggregatorV3Interface.sol"; - -contract MockETHLINKAggregator is AggregatorV3Interface { - int256 public answer; - - constructor(int256 _answer) public { - answer = _answer; - } - - function decimals() external view override returns (uint8) { - return 18; - } - - function description() external view override returns (string memory) { - return "MockETHLINKAggregator"; - } - - function version() external view override returns (uint256) { - return 1; - } - - function getRoundData(uint80 _roundId) - external - view - override - returns ( - uint80 roundId, - int256 ans, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } - - function latestRoundData() - external - view - override - returns ( - uint80 roundId, - int256 ans, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return (1, answer, block.timestamp, block.timestamp, 1); - } -} diff --git a/contracts/src/v0.6/tests/MockGASAggregator.sol b/contracts/src/v0.6/tests/MockGASAggregator.sol deleted file mode 100644 index 271e79e1e21..00000000000 --- a/contracts/src/v0.6/tests/MockGASAggregator.sol +++ /dev/null @@ -1,38 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../interfaces/AggregatorV3Interface.sol"; - -contract MockGASAggregator is AggregatorV3Interface { - int256 public answer; - constructor (int256 _answer) public { - answer = _answer; - } - function decimals() external override view returns (uint8) { - return 18; - } - function description() external override view returns (string memory) { - return "MockGASAggregator"; - } - function version() external override view returns (uint256) { - return 1; - } - function getRoundData(uint80 _roundId) external override view returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) { - return (1, answer, block.timestamp, block.timestamp, 1); - } - function latestRoundData() external override view returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) { - return (1, answer, block.timestamp, block.timestamp, 1); - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/tests/MockOracle.sol b/contracts/src/v0.6/tests/MockOracle.sol deleted file mode 100644 index 7c86d29dc28..00000000000 --- a/contracts/src/v0.6/tests/MockOracle.sol +++ /dev/null @@ -1,204 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../LinkTokenReceiver.sol"; -import "../interfaces/ChainlinkRequestInterface.sol"; -import "../interfaces/LinkTokenInterface.sol"; -import "../vendor/SafeMathChainlink.sol"; - -/** - * @title The Chainlink Mock Oracle contract - * @notice Chainlink smart contract developers can use this to test their contracts - */ -contract MockOracle is ChainlinkRequestInterface, LinkTokenReceiver { - using SafeMathChainlink for uint256; - - uint256 constant public EXPIRY_TIME = 5 minutes; - uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000; - - struct Request { - address callbackAddr; - bytes4 callbackFunctionId; - } - - LinkTokenInterface internal LinkToken; - mapping(bytes32 => Request) private commitments; - - event OracleRequest( - bytes32 indexed specId, - address requester, - bytes32 requestId, - uint256 payment, - address callbackAddr, - bytes4 callbackFunctionId, - uint256 cancelExpiration, - uint256 dataVersion, - bytes data - ); - - event CancelOracleRequest( - bytes32 indexed requestId - ); - - /** - * @notice Deploy with the address of the LINK token - * @dev Sets the LinkToken address for the imported LinkTokenInterface - * @param _link The address of the LINK token - */ - constructor( - address _link - ) - public - { - LinkToken = LinkTokenInterface(_link); // external but already deployed and unalterable - } - - /** - * @notice Creates the Chainlink request - * @dev Stores the hash of the params as the on-chain commitment for the request. - * Emits OracleRequest event for the Chainlink node to detect. - * @param _sender The sender of the request - * @param _payment The amount of payment given (specified in wei) - * @param _specId The Job Specification ID - * @param _callbackAddress The callback address for the response - * @param _callbackFunctionId The callback function ID for the response - * @param _nonce The nonce sent by the requester - * @param _dataVersion The specified data version - * @param _data The CBOR payload of the request - */ - function oracleRequest( - address _sender, - uint256 _payment, - bytes32 _specId, - address _callbackAddress, - bytes4 _callbackFunctionId, - uint256 _nonce, - uint256 _dataVersion, - bytes calldata _data - ) - external - override - onlyLINK() - checkCallbackAddress(_callbackAddress) - { - bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce)); - require(commitments[requestId].callbackAddr == address(0), "Must use a unique ID"); - // solhint-disable-next-line not-rely-on-time - uint256 expiration = now.add(EXPIRY_TIME); - - commitments[requestId] = Request( - _callbackAddress, - _callbackFunctionId - ); - - emit OracleRequest( - _specId, - _sender, - requestId, - _payment, - _callbackAddress, - _callbackFunctionId, - expiration, - _dataVersion, - _data); - } - - /** - * @notice Called by the Chainlink node to fulfill requests - * @dev Given params must hash back to the commitment stored from `oracleRequest`. - * Will call the callback address' callback function without bubbling up error - * checking in a `require` so that the node can get paid. - * @param _requestId The fulfillment request ID that must match the requester's - * @param _data The data to return to the consuming contract - * @return Status if the external call was successful - */ - function fulfillOracleRequest( - bytes32 _requestId, - bytes32 _data - ) - external - isValidRequest(_requestId) - returns ( - bool - ) - { - Request memory req = commitments[_requestId]; - delete commitments[_requestId]; - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = req.callbackAddr.call(abi.encodeWithSelector(req.callbackFunctionId, _requestId, _data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - /** - * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK - * sent for the request back to the requester's address. - * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid - * Emits CancelOracleRequest event. - * @param _requestId The request ID - * @param _payment The amount of payment given (specified in wei) - * @param _expiration The time of the expiration for the request - */ - function cancelOracleRequest( - bytes32 _requestId, - uint256 _payment, - bytes4, - uint256 _expiration - ) - external - override - { - require(commitments[_requestId].callbackAddr != address(0), "Must use a unique ID"); - // solhint-disable-next-line not-rely-on-time - require(_expiration <= now, "Request is not expired"); - - delete commitments[_requestId]; - emit CancelOracleRequest(_requestId); - - assert(LinkToken.transfer(msg.sender, _payment)); - } - - /** - * @notice Returns the address of the LINK token - * @dev This is the public implementation for chainlinkTokenAddress, which is - * an internal method of the ChainlinkClient contract - */ - function getChainlinkToken() - public - view - override - returns ( - address - ) - { - return address(LinkToken); - } - - // MODIFIERS - - /** - * @dev Reverts if request ID does not exist - * @param _requestId The given request ID to check in stored `commitments` - */ - modifier isValidRequest( - bytes32 _requestId - ) { - require(commitments[_requestId].callbackAddr != address(0), "Must have a valid requestId"); - _; - } - - - /** - * @dev Reverts if the callback address is the LINK token - * @param _to The callback address - */ - modifier checkCallbackAddress( - address _to - ) { - require(_to != address(LinkToken), "Cannot callback to LINK"); - _; - } - -} diff --git a/contracts/src/v0.6/tests/MockV3Aggregator.sol b/contracts/src/v0.6/tests/MockV3Aggregator.sol deleted file mode 100644 index b382281ea7c..00000000000 --- a/contracts/src/v0.6/tests/MockV3Aggregator.sol +++ /dev/null @@ -1,109 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../interfaces/AggregatorV2V3Interface.sol"; - -/** - * @title MockV3Aggregator - * @notice Based on the FluxAggregator contract - * @notice Use this contract when you need to test - * other contract's ability to read data from an - * aggregator contract, but how the aggregator got - * its answer is unimportant - */ -contract MockV3Aggregator is AggregatorV2V3Interface { - uint256 constant public override version = 0; - - uint8 public override decimals; - int256 public override latestAnswer; - uint256 public override latestTimestamp; - uint256 public override latestRound; - - mapping(uint256 => int256) public override getAnswer; - mapping(uint256 => uint256) public override getTimestamp; - mapping(uint256 => uint256) private getStartedAt; - - constructor( - uint8 _decimals, - int256 _initialAnswer - ) public { - decimals = _decimals; - updateAnswer(_initialAnswer); - } - - function updateAnswer( - int256 _answer - ) public { - latestAnswer = _answer; - latestTimestamp = block.timestamp; - latestRound++; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = block.timestamp; - getStartedAt[latestRound] = block.timestamp; - } - - function updateRoundData( - uint80 _roundId, - int256 _answer, - uint256 _timestamp, - uint256 _startedAt - ) public { - latestRound = _roundId; - latestAnswer = _answer; - latestTimestamp = _timestamp; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = _timestamp; - getStartedAt[latestRound] = _startedAt; - } - - function getRoundData(uint80 _roundId) - external - view - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return ( - _roundId, - getAnswer[_roundId], - getStartedAt[_roundId], - getTimestamp[_roundId], - _roundId - ); - } - - function latestRoundData() - external - view - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return ( - uint80(latestRound), - getAnswer[latestRound], - getStartedAt[latestRound], - getTimestamp[latestRound], - uint80(latestRound) - ); - } - - function description() - external - view - override - returns (string memory) - { - return "v0.6/tests/MockV3Aggregator.sol"; - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/tests/MultiWordConsumer.sol b/contracts/src/v0.6/tests/MultiWordConsumer.sol deleted file mode 100644 index a2ff5d4080e..00000000000 --- a/contracts/src/v0.6/tests/MultiWordConsumer.sol +++ /dev/null @@ -1,88 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../ChainlinkClient.sol"; - -contract MultiWordConsumer is ChainlinkClient{ - bytes32 internal specId; - bytes public currentPrice; - - bytes32 public first; - bytes32 public second; - - event RequestFulfilled( - bytes32 indexed requestId, // User-defined ID - bytes indexed price - ); - - event RequestMultipleFulfilled( - bytes32 indexed requestId, - bytes32 indexed first, - bytes32 indexed second - ); - - constructor(address _link, address _oracle, bytes32 _specId) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - specId = _specId; - } - - function requestEthereumPrice(string memory _currency, uint256 _payment) public { - requestEthereumPriceByCallback(_currency, _payment, address(this)); - } - - function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public { - Chainlink.Request memory req = buildChainlinkRequest(specId, _callback, this.fulfillBytes.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = _currency; - req.addStringArray("path", path); - sendChainlinkRequest(req, _payment); - } - - function requestMultipleParameters(string memory _currency, uint256 _payment) public { - Chainlink.Request memory req = buildChainlinkRequest(specId, address(this), this.fulfillMultipleParameters.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = _currency; - req.addStringArray("path", path); - sendChainlinkRequest(req, _payment); - } - - function cancelRequest( - address _oracle, - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress()); - require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); - } - - function addExternalRequest(address _oracle, bytes32 _requestId) external { - addChainlinkExternalRequest(_oracle, _requestId); - } - - function fulfillMultipleParameters(bytes32 _requestId, bytes32 _first, bytes32 _second) - public - recordChainlinkFulfillment(_requestId) - { - emit RequestMultipleFulfilled(_requestId, _first, _second); - first = _first; - second = _second; - } - - function fulfillBytes(bytes32 _requestId, bytes memory _price) - public - recordChainlinkFulfillment(_requestId) - { - emit RequestFulfilled(_requestId, _price); - currentPrice = _price; - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/tests/Reverter.sol b/contracts/src/v0.6/tests/Reverter.sol deleted file mode 100644 index a262fbe5592..00000000000 --- a/contracts/src/v0.6/tests/Reverter.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -contract Reverter { - - fallback() external payable { - require(false, "Raised by Reverter.sol"); - } - -} diff --git a/contracts/src/v0.6/tests/TestAPIConsumer.sol b/contracts/src/v0.6/tests/TestAPIConsumer.sol deleted file mode 100644 index e16e6916206..00000000000 --- a/contracts/src/v0.6/tests/TestAPIConsumer.sol +++ /dev/null @@ -1,123 +0,0 @@ -/** This example code is designed to quickly deploy an example contract using Remix. - * If you have never used Remix, try our example walkthrough: https://docs.chain.link/docs/example-walkthrough - * You will need testnet ETH and LINK. - * - Kovan ETH faucet: https://faucet.kovan.network/ - * - Kovan LINK faucet: https://kovan.chain.link/ - */ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "../interfaces/LinkTokenInterface.sol"; -import "../ChainlinkClient.sol"; -import "../vendor/Ownable.sol"; - -/** - * @title TestAPIConsumer is an example contract which requests data from - * the Chainlink network - * @dev This contract is designed to work on multiple networks, including - * local test networks - */ -contract TestAPIConsumer is ChainlinkClient, Ownable { - uint256 public currentRoundID = 0; - uint256 public data; - bytes4 public selector; - - event PerfMetricsEvent(uint256 roundID, bytes32 requestId, uint256 timestamp); - - - /** - * @notice Deploy the contract with a specified address for the LINK - * and Oracle contract addresses - * @dev Sets the storage for the specified addresses - * @param _link The address of the LINK token contract - */ - constructor(address _link) public { - if (_link == address(0)) { - setPublicChainlinkToken(); - } else { - setChainlinkToken(_link); - } - } - - /** - * @notice Returns the address of the LINK token - * @dev This is the public implementation for chainlinkTokenAddress, which is - * an internal method of the ChainlinkClient contract - */ - function getChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); - } - - /** - * @notice Creates a request to the specified Oracle contract address - * @dev This function ignores the stored Oracle contract address and - * will instead send the request to the address specified - * @param _oracle The Oracle contract address to send the request to - * @param _jobId The bytes32 JobID to be executed - * @param _url The URL to fetch data from - * @param _path The dot-delimited path to parse of the response - * @param _times The number to multiply the result by - */ - function createRequestTo( - address _oracle, - bytes32 _jobId, - uint256 _payment, - string memory _url, - string memory _path, - int256 _times - ) - public - onlyOwner - returns (bytes32 requestId) - { - selector = this.fulfill.selector; - Chainlink.Request memory req = buildChainlinkRequest(_jobId, address(this), this.fulfill.selector); - req.add("get", _url); - req.add("path", _path); - req.addInt("times", _times); - requestId = sendChainlinkRequestTo(_oracle, req, _payment); - } - - /** - * @notice The fulfill method from requests created by this contract - * @dev The recordChainlinkFulfillment protects this function from being called - * by anyone other than the oracle address that the request was sent to - * @param _requestId The ID that was generated for the request - * @param _data The answer provided by the oracle - */ - function fulfill(bytes32 _requestId, uint256 _data) - public - { - data = _data; - currentRoundID += 1; - emit PerfMetricsEvent(currentRoundID, _requestId, block.timestamp); - } - - /** - * @notice Allows the owner to withdraw any LINK balance on the contract - */ - function withdrawLink() public onlyOwner { - LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress()); - require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer"); - } - - /** - * @notice Call this method if no response is received within 5 minutes - * @param _requestId The ID that was generated for the request to cancel - * @param _payment The payment specified for the request to cancel - * @param _callbackFunctionId The bytes4 callback function ID specified for - * the request to cancel - * @param _expiration The expiration generated for the request to cancel - */ - function cancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) - public - onlyOwner - { - cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } -} diff --git a/contracts/src/v0.6/tests/VRFConsumer.sol b/contracts/src/v0.6/tests/VRFConsumer.sol deleted file mode 100644 index ff0a09fb8c9..00000000000 --- a/contracts/src/v0.6/tests/VRFConsumer.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../interfaces/LinkTokenInterface.sol"; -import "../VRFCoordinator.sol"; -import "../VRFConsumerBase.sol"; - -contract VRFConsumer is VRFConsumerBase { - - uint256 public currentRoundID = 0; - uint256 public randomnessOutput; - bytes32 public requestId; - - constructor(address _vrfCoordinator, address _link) public - // solhint-disable-next-line no-empty-blocks - VRFConsumerBase(_vrfCoordinator, _link) { /* empty */ } - - function fulfillRandomness(bytes32 _requestId, uint256 _randomness) - internal override - { - randomnessOutput = _randomness; - requestId = _requestId; - currentRoundID += 1; - } - - function testRequestRandomness(bytes32 _keyHash, uint256 _fee) - external returns (bytes32 requestId) - { - return requestRandomness(_keyHash, _fee); - } -} diff --git a/contracts/src/v0.6/tests/VRFCoordinatorMock.sol b/contracts/src/v0.6/tests/VRFCoordinatorMock.sol deleted file mode 100644 index dd8b8063bf1..00000000000 --- a/contracts/src/v0.6/tests/VRFCoordinatorMock.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../interfaces/LinkTokenInterface.sol"; -import "../VRFConsumerBase.sol"; - -contract VRFCoordinatorMock { - - LinkTokenInterface public LINK; - - event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed); - - constructor(address linkAddress) public { - LINK = LinkTokenInterface(linkAddress); - } - - function onTokenTransfer(address sender, uint256 fee, bytes memory _data) - public - onlyLINK - { - (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); - emit RandomnessRequest(sender, keyHash, seed); - } - - function callBackWithRandomness( - bytes32 requestId, - uint256 randomness, - address consumerContract - ) public { - VRFConsumerBase v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomness.selector, requestId, randomness); - uint256 b = 206000; - require(gasleft() >= b, "not enough gas for consumer"); - (bool success,) = consumerContract.call(resp); - } - - modifier onlyLINK() { - require(msg.sender == address(LINK), "Must use LINK token"); - _; - } -} \ No newline at end of file diff --git a/contracts/src/v0.6/tests/VRFRequestIDBaseTestHelper.sol b/contracts/src/v0.6/tests/VRFRequestIDBaseTestHelper.sol deleted file mode 100644 index f1b81f210ed..00000000000 --- a/contracts/src/v0.6/tests/VRFRequestIDBaseTestHelper.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../VRFRequestIDBase.sol"; - -contract VRFRequestIDBaseTestHelper is VRFRequestIDBase { - - function makeVRFInputSeed_(bytes32 _keyHash, uint256 _userSeed, - address _requester, uint256 _nonce) - public pure returns (uint256) { - return makeVRFInputSeed(_keyHash, _userSeed, _requester, _nonce); - } - - function makeRequestId_( - bytes32 _keyHash, uint256 _vRFInputSeed) public pure returns (bytes32) { - return makeRequestId(_keyHash, _vRFInputSeed); - } -} diff --git a/contracts/src/v0.6/tests/VRFTestHelper.sol b/contracts/src/v0.6/tests/VRFTestHelper.sol deleted file mode 100644 index d79e71dce1b..00000000000 --- a/contracts/src/v0.6/tests/VRFTestHelper.sol +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity 0.6.6; - -import "../VRF.sol"; - -/** *********************************************************************** - @notice Testing harness for VRF.sol, exposing its internal methods. Not to - @notice be used for production. -*/ -contract VRFTestHelper is VRF { - function bigModExp_(uint256 base, uint256 exponent) public view returns (uint256) { - return super.bigModExp(base, exponent); - } - function squareRoot_(uint256 x) public view returns (uint256) { - return super.squareRoot(x); - } - function ySquared_(uint256 x) public pure returns (uint256) { - return super.ySquared(x); - } - function fieldHash_(bytes memory b) public pure returns (uint256) { - return super.fieldHash(b); - } - function hashToCurve_(uint256[2] memory pk, uint256 x) public view returns(uint256[2] memory) { - return super.hashToCurve(pk, x); - } - function ecmulVerify_(uint256[2] memory x, uint256 scalar, uint256[2] memory q) public pure returns (bool) { - return super.ecmulVerify(x, scalar, q); - } - function projectiveECAdd_(uint256 px, uint256 py, uint256 qx, uint256 qy) public pure returns(uint256, uint256, uint256) { - return super.projectiveECAdd(px, py, qx, qy); - } - function affineECAdd_(uint256[2] memory p1, uint256[2] memory p2, uint256 invZ) public pure returns (uint256[2] memory) { - return super.affineECAdd(p1, p2, invZ); - } - function verifyLinearCombinationWithGenerator_(uint256 c, uint256[2] memory p, uint256 s, address lcWitness) public pure returns (bool) { - return super.verifyLinearCombinationWithGenerator(c, p, s, lcWitness); - } - function linearCombination_(uint256 c, uint256[2] memory p1, uint256[2] memory cp1Witness, uint256 s, uint256[2] memory p2, uint256[2] memory sp2Witness, uint256 zInv) public pure returns (uint256[2] memory) { - return super.linearCombination(c, p1, cp1Witness, s, p2, sp2Witness, zInv); - } - function scalarFromCurvePoints_(uint256[2] memory hash, uint256[2] memory pk, uint256[2] memory gamma, address uWitness, uint256[2] memory v) public pure returns (uint256) { - return super.scalarFromCurvePoints(hash, pk, gamma, uWitness, v); - } - function verifyVRFProof_( - uint256[2] memory pk, uint256[2] memory gamma, uint256 c, uint256 s, - uint256 seed, address uWitness, uint256[2] memory cGammaWitness, - uint256[2] memory sHashWitness, uint256 zInv) - public view { - super.verifyVRFProof(pk, gamma, c, s, seed, uWitness, cGammaWitness, sHashWitness, zInv); - } - function randomValueFromVRFProof_(bytes memory proof) - public view returns (uint256 output) { - return super.randomValueFromVRFProof(proof); - } -} diff --git a/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol b/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol deleted file mode 100644 index fb48f360814..00000000000 --- a/contracts/src/v0.6/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright 2021-2022, Offchain Labs, Inc. -// For license information, see https://github.com/nitro/blob/master/LICENSE -// SPDX-License-Identifier: BUSL-1.1 - -pragma solidity >=0.4.21 <0.9.0; - -/** - * @title System level functionality - * @notice For use by contracts to interact with core L2-specific functionality. - * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064. - */ -interface ArbSys { - /** - * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0) - * @return block number as int - */ - function arbBlockNumber() external view returns (uint256); - - /** - * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum) - * @return block hash - */ - function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32); - - /** - * @notice Gets the rollup's unique chain identifier - * @return Chain identifier as int - */ - function arbChainID() external view returns (uint256); - - /** - * @notice Get internal version number identifying an ArbOS build - * @return version number as int - */ - function arbOSVersion() external view returns (uint256); - - /** - * @notice Returns 0 since Nitro has no concept of storage gas - * @return uint 0 - */ - function getStorageGasAvailable() external view returns (uint256); - - /** - * @notice (deprecated) check if current call is top level (meaning it was triggered by an EoA or a L1 contract) - * @dev this call has been deprecated and may be removed in a future release - * @return true if current execution frame is not a call by another L2 contract - */ - function isTopLevelCall() external view returns (bool); - - /** - * @notice map L1 sender contract address to its L2 alias - * @param sender sender address - * @param unused argument no longer used - * @return aliased sender address - */ - function mapL1SenderContractAddressToL2Alias(address sender, address unused) - external - pure - returns (address); - - /** - * @notice check if the caller (of this caller of this) is an aliased L1 contract address - * @return true iff the caller's address is an alias for an L1 contract address - */ - function wasMyCallersAddressAliased() external view returns (bool); - - /** - * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing - * @return address of the caller's caller, without applying L1 contract address aliasing - */ - function myCallersAddressWithoutAliasing() external view returns (address); - - /** - * @notice Send given amount of Eth to dest from sender. - * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data. - * @param destination recipient address on L1 - * @return unique identifier for this L2-to-L1 transaction. - */ - function withdrawEth(address destination) - external - payable - returns (uint256); - - /** - * @notice Send a transaction to L1 - * @dev it is not possible to execute on the L1 any L2-to-L1 transaction which contains data - * to a contract address without any code (as enforced by the Bridge contract). - * @param destination recipient address on L1 - * @param data (optional) calldata for L1 contract call - * @return a unique identifier for this L2-to-L1 transaction. - */ - function sendTxToL1(address destination, bytes calldata data) - external - payable - returns (uint256); - - /** - * @notice Get send Merkle tree state - * @return size number of sends in the history - * @return root root hash of the send history - * @return partials hashes of partial subtrees in the send history tree - */ - function sendMerkleTreeState() - external - view - returns ( - uint256 size, - bytes32 root, - bytes32[] memory partials - ); - - /** - * @notice creates a send txn from L2 to L1 - * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf - */ - event L2ToL1Tx( - address caller, - address indexed destination, - uint256 indexed hash, - uint256 indexed position, - uint256 arbBlockNum, - uint256 ethBlockNum, - uint256 timestamp, - uint256 callvalue, - bytes data - ); - - /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade - event L2ToL1Transaction( - address caller, - address indexed destination, - uint256 indexed uniqueId, - uint256 indexed batchNumber, - uint256 indexInBatch, - uint256 arbBlockNum, - uint256 ethBlockNum, - uint256 timestamp, - uint256 callvalue, - bytes data - ); - - /** - * @notice logs a merkle branch for proof synthesis - * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event - * @param hash the merkle hash - * @param position = (level << 192) + leaf - */ - event SendMerkleUpdate( - uint256 indexed reserved, - bytes32 indexed hash, - uint256 indexed position - ); -} diff --git a/contracts/src/v0.6/vendor/BufferChainlink.sol b/contracts/src/v0.6/vendor/BufferChainlink.sol deleted file mode 100644 index 2ef5342b6f0..00000000000 --- a/contracts/src/v0.6/vendor/BufferChainlink.sol +++ /dev/null @@ -1,302 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** -* @dev A library for working with mutable byte buffers in Solidity. -* -* Byte buffers are mutable and expandable, and provide a variety of primitives -* for writing to them. At any time you can fetch a bytes object containing the -* current contents of the buffer. The bytes object should not be stored between -* operations, as it may change due to resizing of the buffer. -*/ -library BufferChainlink { - /** - * @dev Represents a mutable buffer. Buffers have a current value (buf) and - * a capacity. The capacity may be longer than the current value, in - * which case it can be extended without the need to allocate more memory. - */ - struct buffer { - bytes buf; - uint capacity; - } - - /** - * @dev Initializes a buffer with an initial capacity. - * @param buf The buffer to initialize. - * @param capacity The number of bytes of space to allocate the buffer. - * @return The buffer, for chaining. - */ - function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) { - if (capacity % 32 != 0) { - capacity += 32 - (capacity % 32); - } - // Allocate space for the buffer data - buf.capacity = capacity; - assembly { - let ptr := mload(0x40) - mstore(buf, ptr) - mstore(ptr, 0) - mstore(0x40, add(32, add(ptr, capacity))) - } - return buf; - } - - /** - * @dev Initializes a new buffer from an existing bytes object. - * Changes to the buffer may mutate the original value. - * @param b The bytes object to initialize the buffer with. - * @return A new buffer. - */ - function fromBytes(bytes memory b) internal pure returns(buffer memory) { - buffer memory buf; - buf.buf = b; - buf.capacity = b.length; - return buf; - } - - function resize(buffer memory buf, uint capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); - } - - function max(uint a, uint b) private pure returns(uint) { - if (a > b) { - return a; - } - return b; - } - - /** - * @dev Sets buffer length to 0. - * @param buf The buffer to truncate. - * @return The original buffer, for chaining.. - */ - function truncate(buffer memory buf) internal pure returns (buffer memory) { - assembly { - let bufptr := mload(buf) - mstore(bufptr, 0) - } - return buf; - } - - /** - * @dev Writes a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The start offset to write to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) { - require(len <= data.length); - - if (off + len > buf.capacity) { - resize(buf, max(buf.capacity, len + off) * 2); - } - - uint dest; - uint src; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + offset + sizeof(buffer length) - dest := add(add(bufptr, 32), off) - // Update buffer length if we're extending it - if gt(add(len, off), buflen) { - mstore(bufptr, add(len, off)) - } - src := add(data, 32) - } - - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - uint mask = 256 ** (32 - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - - return buf; - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, len); - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, data.length); - } - - /** - * @dev Writes a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write the byte at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) { - if (off >= buf.capacity) { - resize(buf, buf.capacity * 2); - } - - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + sizeof(buffer length) + off - let dest := add(add(bufptr, off), 32) - mstore8(dest, data) - // Update buffer length if we extended it - if eq(off, buflen) { - mstore(bufptr, add(buflen, 1)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) { - return writeUint8(buf, buf.buf.length, data); - } - - /** - * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (left-aligned). - * @return The original buffer, for chaining. - */ - function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint mask = 256 ** len - 1; - // Right-align data - data = data >> (8 * (32 - len)); - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + off + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) { - return write(buf, off, bytes32(data), 20); - } - - /** - * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chhaining. - */ - function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, bytes32(data), 20); - } - - /** - * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, 32); - } - - /** - * @dev Writes an integer to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (right-aligned). - * @return The original buffer, for chaining. - */ - function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint mask = 256 ** len - 1; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + off + sizeof(buffer length) + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) { - return writeInt(buf, buf.buf.length, data, len); - } -} diff --git a/contracts/src/v0.6/vendor/CBORChainlink.sol b/contracts/src/v0.6/vendor/CBORChainlink.sol deleted file mode 100644 index 90a1b1bd6d6..00000000000 --- a/contracts/src/v0.6/vendor/CBORChainlink.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >= 0.4.19; - -import { BufferChainlink } from "./BufferChainlink.sol"; - -library CBORChainlink { - using BufferChainlink for BufferChainlink.buffer; - - uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; - uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; - uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; - uint8 private constant MAJOR_TYPE_TAG = 6; - uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - - uint8 private constant TAG_TYPE_BIGNUM = 2; - uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; - - function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { - if(value <= 23) { - buf.appendUint8(uint8((major << 5) | value)); - } else if(value <= 0xFF) { - buf.appendUint8(uint8((major << 5) | 24)); - buf.appendInt(value, 1); - } else if(value <= 0xFFFF) { - buf.appendUint8(uint8((major << 5) | 25)); - buf.appendInt(value, 2); - } else if(value <= 0xFFFFFFFF) { - buf.appendUint8(uint8((major << 5) | 26)); - buf.appendInt(value, 4); - } else { - buf.appendUint8(uint8((major << 5) | 27)); - buf.appendInt(value, 8); - } - } - - function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { - buf.appendUint8(uint8((major << 5) | 31)); - } - - function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { - if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, value); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); - } - } - - function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { - if(value < -0x10000000000000000) { - encodeSignedBigNum(buf, value); - } else if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, uint(value)); - } else if(value >= 0) { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value)); - } - } - - function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); - buf.append(value); - } - - function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); - encodeBytes(buf, abi.encode(value)); - } - - function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); - encodeBytes(buf, abi.encode(uint(-1 - input))); - } - - function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); - buf.append(bytes(value)); - } - - function startArray(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); - } - - function startMap(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); - } - - function endSequence(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); - } -} diff --git a/contracts/src/v0.6/vendor/ENSResolver.sol b/contracts/src/v0.6/vendor/ENSResolver.sol deleted file mode 100644 index a2aff795186..00000000000 --- a/contracts/src/v0.6/vendor/ENSResolver.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -abstract contract ENSResolver { - function addr(bytes32 node) public view virtual returns (address); -} diff --git a/contracts/src/v0.6/vendor/Ownable.sol b/contracts/src/v0.6/vendor/Ownable.sol deleted file mode 100644 index f0299db3ec8..00000000000 --- a/contracts/src/v0.6/vendor/Ownable.sol +++ /dev/null @@ -1,66 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** - * @dev Contract module which provides a basic access control mechanism, where - * there is an account (an owner) that can be granted exclusive access to - * specific functions. - * - * This module is used through inheritance. It will make available the modifier - * `onlyOwner`, which can be aplied to your functions to restrict their use to - * the owner. - * - * This contract has been modified to remove the revokeOwnership function - */ -contract Ownable { - address private _owner; - - event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); - - /** - * @dev Initializes the contract setting the deployer as the initial owner. - */ - constructor () internal { - _owner = msg.sender; - emit OwnershipTransferred(address(0), _owner); - } - - /** - * @dev Returns the address of the current owner. - */ - function owner() public view returns (address) { - return _owner; - } - - /** - * @dev Throws if called by any account other than the owner. - */ - modifier onlyOwner() { - require(isOwner(), "Ownable: caller is not the owner"); - _; - } - - /** - * @dev Returns true if the caller is the current owner. - */ - function isOwner() public view returns (bool) { - return msg.sender == _owner; - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - * Can only be called by the current owner. - */ - function transferOwnership(address newOwner) public onlyOwner { - _transferOwnership(newOwner); - } - - /** - * @dev Transfers ownership of the contract to a new account (`newOwner`). - */ - function _transferOwnership(address newOwner) internal { - require(newOwner != address(0), "Ownable: new owner is the zero address"); - emit OwnershipTransferred(_owner, newOwner); - _owner = newOwner; - } -} diff --git a/contracts/src/v0.6/vendor/SafeMathChainlink.sol b/contracts/src/v0.6/vendor/SafeMathChainlink.sol deleted file mode 100644 index 39d73a5e85c..00000000000 --- a/contracts/src/v0.6/vendor/SafeMathChainlink.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMathChainlink { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.7/AuthorizedForwarder.sol b/contracts/src/v0.7/AuthorizedForwarder.sol deleted file mode 100644 index 30cfb2c1ed7..00000000000 --- a/contracts/src/v0.7/AuthorizedForwarder.sol +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./interfaces/OperatorInterface.sol"; -import "./ConfirmedOwnerWithProposal.sol"; -import "./AuthorizedReceiver.sol"; -import "./vendor/Address.sol"; - -contract AuthorizedForwarder is ConfirmedOwnerWithProposal, AuthorizedReceiver { - using Address for address; - - address public immutable getChainlinkToken; - - event OwnershipTransferRequestedWithMessage(address indexed from, address indexed to, bytes message); - - constructor( - address link, - address owner, - address recipient, - bytes memory message - ) ConfirmedOwnerWithProposal(owner, recipient) { - require(link != address(0)); - getChainlinkToken = link; - if (recipient != address(0)) { - emit OwnershipTransferRequestedWithMessage(owner, recipient, message); - } - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual returns (string memory) { - return "AuthorizedForwarder 1.0.0"; - } - - /** - * @notice Forward a call to another contract - * @dev Only callable by an authorized sender - * @param to address - * @param data to forward - */ - function forward(address to, bytes calldata data) external validateAuthorizedSender { - require(to != getChainlinkToken, "Cannot forward to Link token"); - _forward(to, data); - } - - /** - * @notice Forward a call to another contract - * @dev Only callable by the owner - * @param to address - * @param data to forward - */ - function ownerForward(address to, bytes calldata data) external onlyOwner { - _forward(to, data); - } - - /** - * @notice Transfer ownership with instructions for recipient - * @param to address proposed recipient of ownership - * @param message instructions for recipient upon accepting ownership - */ - function transferOwnershipWithMessage(address to, bytes calldata message) external { - transferOwnership(to); - emit OwnershipTransferRequestedWithMessage(msg.sender, to, message); - } - - /** - * @notice concrete implementation of AuthorizedReceiver - * @return bool of whether sender is authorized - */ - function _canSetAuthorizedSenders() internal view override returns (bool) { - return owner() == msg.sender; - } - - /** - * @notice common forwarding functionality and validation - */ - function _forward(address to, bytes calldata data) private { - require(to.isContract(), "Must forward to a contract"); - (bool success, bytes memory result) = to.call(data); - if (!success) { - if (result.length == 0) revert("Forwarded call reverted without reason"); - assembly { - revert(add(32, result), mload(result)) - } - } - } -} diff --git a/contracts/src/v0.7/AuthorizedReceiver.sol b/contracts/src/v0.7/AuthorizedReceiver.sol deleted file mode 100644 index daa2792f5a4..00000000000 --- a/contracts/src/v0.7/AuthorizedReceiver.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./interfaces/AuthorizedReceiverInterface.sol"; - -abstract contract AuthorizedReceiver is AuthorizedReceiverInterface { - mapping(address => bool) private s_authorizedSenders; - address[] private s_authorizedSenderList; - - event AuthorizedSendersChanged(address[] senders, address changedBy); - - /** - * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow. - * @param senders The addresses of the authorized Chainlink node - */ - function setAuthorizedSenders(address[] calldata senders) external override validateAuthorizedSenderSetter { - require(senders.length > 0, "Must have at least 1 sender"); - // Set previous authorized senders to false - uint256 authorizedSendersLength = s_authorizedSenderList.length; - for (uint256 i = 0; i < authorizedSendersLength; i++) { - s_authorizedSenders[s_authorizedSenderList[i]] = false; - } - // Set new to true - for (uint256 i = 0; i < senders.length; i++) { - require(s_authorizedSenders[senders[i]] == false, "Must not have duplicate senders"); - s_authorizedSenders[senders[i]] = true; - } - // Replace list - s_authorizedSenderList = senders; - emit AuthorizedSendersChanged(senders, msg.sender); - } - - /** - * @notice Retrieve a list of authorized senders - * @return array of addresses - */ - function getAuthorizedSenders() external view override returns (address[] memory) { - return s_authorizedSenderList; - } - - /** - * @notice Use this to check if a node is authorized for fulfilling requests - * @param sender The address of the Chainlink node - * @return The authorization status of the node - */ - function isAuthorizedSender(address sender) public view override returns (bool) { - return s_authorizedSenders[sender]; - } - - /** - * @notice customizable guard of who can update the authorized sender list - * @return bool whether sender can update authorized sender list - */ - function _canSetAuthorizedSenders() internal virtual returns (bool); - - /** - * @notice validates the sender is an authorized sender - */ - function _validateIsAuthorizedSender() internal view { - require(isAuthorizedSender(msg.sender), "Not authorized sender"); - } - - /** - * @notice prevents non-authorized addresses from calling this method - */ - modifier validateAuthorizedSender() { - _validateIsAuthorizedSender(); - _; - } - - /** - * @notice prevents non-authorized addresses from calling this method - */ - modifier validateAuthorizedSenderSetter() { - require(_canSetAuthorizedSenders(), "Cannot set authorized senders"); - _; - } -} diff --git a/contracts/src/v0.7/Chainlink.sol b/contracts/src/v0.7/Chainlink.sol deleted file mode 100644 index e08d87ceabf..00000000000 --- a/contracts/src/v0.7/Chainlink.sol +++ /dev/null @@ -1,135 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import {CBORChainlink} from "./vendor/CBORChainlink.sol"; -import {BufferChainlink} from "./vendor/BufferChainlink.sol"; - -/** - * @title Library for common Chainlink functions - * @dev Uses imported CBOR library for encoding to buffer - */ -library Chainlink { - uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase - - using CBORChainlink for BufferChainlink.buffer; - - struct Request { - bytes32 id; - address callbackAddress; - bytes4 callbackFunctionId; - uint256 nonce; - BufferChainlink.buffer buf; - } - - /** - * @notice Initializes a Chainlink request - * @dev Sets the ID, callback address, and callback function signature on the request - * @param self The uninitialized request - * @param jobId The Job Specification ID - * @param callbackAddr The callback address - * @param callbackFunc The callback function signature - * @return The initialized request - */ - function initialize( - Request memory self, - bytes32 jobId, - address callbackAddr, - bytes4 callbackFunc - ) internal pure returns (Chainlink.Request memory) { - BufferChainlink.init(self.buf, defaultBufferSize); - self.id = jobId; - self.callbackAddress = callbackAddr; - self.callbackFunctionId = callbackFunc; - return self; - } - - /** - * @notice Sets the data for the buffer without encoding CBOR on-chain - * @dev CBOR can be closed with curly-brackets {} or they can be left off - * @param self The initialized request - * @param data The CBOR data - */ - function setBuffer(Request memory self, bytes memory data) internal pure { - BufferChainlink.init(self.buf, data.length); - BufferChainlink.append(self.buf, data); - } - - /** - * @notice Adds a string value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The string value to add - */ - function add( - Request memory self, - string memory key, - string memory value - ) internal pure { - self.buf.encodeString(key); - self.buf.encodeString(value); - } - - /** - * @notice Adds a bytes value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The bytes value to add - */ - function addBytes( - Request memory self, - string memory key, - bytes memory value - ) internal pure { - self.buf.encodeString(key); - self.buf.encodeBytes(value); - } - - /** - * @notice Adds a int256 value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The int256 value to add - */ - function addInt( - Request memory self, - string memory key, - int256 value - ) internal pure { - self.buf.encodeString(key); - self.buf.encodeInt(value); - } - - /** - * @notice Adds a uint256 value to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param value The uint256 value to add - */ - function addUint( - Request memory self, - string memory key, - uint256 value - ) internal pure { - self.buf.encodeString(key); - self.buf.encodeUInt(value); - } - - /** - * @notice Adds an array of strings to the request with a given key name - * @param self The initialized request - * @param key The name of the key - * @param values The array of string values to add - */ - function addStringArray( - Request memory self, - string memory key, - string[] memory values - ) internal pure { - self.buf.encodeString(key); - self.buf.startArray(); - for (uint256 i = 0; i < values.length; i++) { - self.buf.encodeString(values[i]); - } - self.buf.endSequence(); - } -} diff --git a/contracts/src/v0.7/ChainlinkClient.sol b/contracts/src/v0.7/ChainlinkClient.sol deleted file mode 100644 index 48cc048bb67..00000000000 --- a/contracts/src/v0.7/ChainlinkClient.sol +++ /dev/null @@ -1,315 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./Chainlink.sol"; -import "./interfaces/ENSInterface.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/ChainlinkRequestInterface.sol"; -import "./interfaces/OperatorInterface.sol"; -import "./interfaces/PointerInterface.sol"; -import {ENSResolver as ENSResolver_Chainlink} from "./vendor/ENSResolver.sol"; - -/** - * @title The ChainlinkClient contract - * @notice Contract writers can inherit this contract in order to create requests for the - * Chainlink network - */ -abstract contract ChainlinkClient { - using Chainlink for Chainlink.Request; - - uint256 internal constant LINK_DIVISIBILITY = 10**18; - uint256 private constant AMOUNT_OVERRIDE = 0; - address private constant SENDER_OVERRIDE = address(0); - uint256 private constant ORACLE_ARGS_VERSION = 1; - uint256 private constant OPERATOR_ARGS_VERSION = 2; - bytes32 private constant ENS_TOKEN_SUBNAME = keccak256("link"); - bytes32 private constant ENS_ORACLE_SUBNAME = keccak256("oracle"); - address private constant LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571; - - ENSInterface private s_ens; - bytes32 private s_ensNode; - LinkTokenInterface private s_link; - OperatorInterface private s_oracle; - uint256 private s_requestCount = 1; - mapping(bytes32 => address) private s_pendingRequests; - - event ChainlinkRequested(bytes32 indexed id); - event ChainlinkFulfilled(bytes32 indexed id); - event ChainlinkCancelled(bytes32 indexed id); - - /** - * @notice Creates a request that can hold additional parameters - * @param specId The Job Specification ID that the request will be created for - * @param callbackAddr address to operate the callback on - * @param callbackFunctionSignature function signature to use for the callback - * @return A Chainlink Request struct in memory - */ - function buildChainlinkRequest( - bytes32 specId, - address callbackAddr, - bytes4 callbackFunctionSignature - ) internal pure returns (Chainlink.Request memory) { - Chainlink.Request memory req; - return req.initialize(specId, callbackAddr, callbackFunctionSignature); - } - - /** - * @notice Creates a request that can hold additional parameters - * @param specId The Job Specification ID that the request will be created for - * @param callbackFunctionSignature function signature to use for the callback - * @return A Chainlink Request struct in memory - */ - function buildOperatorRequest(bytes32 specId, bytes4 callbackFunctionSignature) - internal - view - returns (Chainlink.Request memory) - { - Chainlink.Request memory req; - return req.initialize(specId, address(this), callbackFunctionSignature); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev Calls `chainlinkRequestTo` with the stored oracle address - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { - return sendChainlinkRequestTo(address(s_oracle), req, payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param oracleAddress The address of the oracle for the request - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendChainlinkRequestTo( - address oracleAddress, - Chainlink.Request memory req, - uint256 payment - ) internal returns (bytes32 requestId) { - uint256 nonce = s_requestCount; - s_requestCount = nonce + 1; - bytes memory encodedRequest = abi.encodeWithSelector( - ChainlinkRequestInterface.oracleRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - req.id, - address(this), - req.callbackFunctionId, - nonce, - ORACLE_ARGS_VERSION, - req.buf.buf - ); - return _rawRequest(oracleAddress, nonce, payment, encodedRequest); - } - - /** - * @notice Creates a Chainlink request to the stored oracle address - * @dev This function supports multi-word response - * @dev Calls `sendOperatorRequestTo` with the stored oracle address - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendOperatorRequest(Chainlink.Request memory req, uint256 payment) internal returns (bytes32) { - return sendOperatorRequestTo(address(s_oracle), req, payment); - } - - /** - * @notice Creates a Chainlink request to the specified oracle address - * @dev This function supports multi-word response - * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to - * send LINK which creates a request on the target oracle contract. - * Emits ChainlinkRequested event. - * @param oracleAddress The address of the oracle for the request - * @param req The initialized Chainlink Request - * @param payment The amount of LINK to send for the request - * @return requestId The request ID - */ - function sendOperatorRequestTo( - address oracleAddress, - Chainlink.Request memory req, - uint256 payment - ) internal returns (bytes32 requestId) { - uint256 nonce = s_requestCount; - s_requestCount = nonce + 1; - bytes memory encodedRequest = abi.encodeWithSelector( - OperatorInterface.operatorRequest.selector, - SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address - AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent - req.id, - req.callbackFunctionId, - nonce, - OPERATOR_ARGS_VERSION, - req.buf.buf - ); - return _rawRequest(oracleAddress, nonce, payment, encodedRequest); - } - - /** - * @notice Make a request to an oracle - * @param oracleAddress The address of the oracle for the request - * @param nonce used to generate the request ID - * @param payment The amount of LINK to send for the request - * @param encodedRequest data encoded for request type specific format - * @return requestId The request ID - */ - function _rawRequest( - address oracleAddress, - uint256 nonce, - uint256 payment, - bytes memory encodedRequest - ) private returns (bytes32 requestId) { - requestId = keccak256(abi.encodePacked(this, nonce)); - s_pendingRequests[requestId] = oracleAddress; - emit ChainlinkRequested(requestId); - require(s_link.transferAndCall(oracleAddress, payment, encodedRequest), "unable to transferAndCall to oracle"); - } - - /** - * @notice Allows a request to be cancelled if it has not been fulfilled - * @dev Requires keeping track of the expiration value emitted from the oracle contract. - * Deletes the request from the `pendingRequests` mapping. - * Emits ChainlinkCancelled event. - * @param requestId The request ID - * @param payment The amount of LINK sent for the request - * @param callbackFunc The callback function specified for the request - * @param expiration The time of the expiration for the request - */ - function cancelChainlinkRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) internal { - OperatorInterface requested = OperatorInterface(s_pendingRequests[requestId]); - delete s_pendingRequests[requestId]; - emit ChainlinkCancelled(requestId); - requested.cancelOracleRequest(requestId, payment, callbackFunc, expiration); - } - - /** - * @notice the next request count to be used in generating a nonce - * @dev starts at 1 in order to ensure consistent gas cost - * @return returns the next request count to be used in a nonce - */ - function getNextRequestCount() internal view returns (uint256) { - return s_requestCount; - } - - /** - * @notice Sets the stored oracle address - * @param oracleAddress The address of the oracle contract - */ - function setChainlinkOracle(address oracleAddress) internal { - s_oracle = OperatorInterface(oracleAddress); - } - - /** - * @notice Sets the LINK token address - * @param linkAddress The address of the LINK token contract - */ - function setChainlinkToken(address linkAddress) internal { - s_link = LinkTokenInterface(linkAddress); - } - - /** - * @notice Sets the Chainlink token address for the public - * network as given by the Pointer contract - */ - function setPublicChainlinkToken() internal { - setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress()); - } - - /** - * @notice Retrieves the stored address of the LINK token - * @return The address of the LINK token - */ - function chainlinkTokenAddress() internal view returns (address) { - return address(s_link); - } - - /** - * @notice Retrieves the stored address of the oracle contract - * @return The address of the oracle contract - */ - function chainlinkOracleAddress() internal view returns (address) { - return address(s_oracle); - } - - /** - * @notice Allows for a request which was created on another contract to be fulfilled - * on this contract - * @param oracleAddress The address of the oracle contract that will fulfill the request - * @param requestId The request ID used for the response - */ - function addChainlinkExternalRequest(address oracleAddress, bytes32 requestId) internal notPendingRequest(requestId) { - s_pendingRequests[requestId] = oracleAddress; - } - - /** - * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS - * @dev Accounts for subnodes having different resolvers - * @param ensAddress The address of the ENS contract - * @param node The ENS node hash - */ - function useChainlinkWithENS(address ensAddress, bytes32 node) internal { - s_ens = ENSInterface(ensAddress); - s_ensNode = node; - bytes32 linkSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_TOKEN_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(linkSubnode)); - setChainlinkToken(resolver.addr(linkSubnode)); - updateChainlinkOracleWithENS(); - } - - /** - * @notice Sets the stored oracle contract with the address resolved by ENS - * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously - */ - function updateChainlinkOracleWithENS() internal { - bytes32 oracleSubnode = keccak256(abi.encodePacked(s_ensNode, ENS_ORACLE_SUBNAME)); - ENSResolver_Chainlink resolver = ENSResolver_Chainlink(s_ens.resolver(oracleSubnode)); - setChainlinkOracle(resolver.addr(oracleSubnode)); - } - - /** - * @notice Ensures that the fulfillment is valid for this contract - * @dev Use if the contract developer prefers methods instead of modifiers for validation - * @param requestId The request ID for fulfillment - */ - function validateChainlinkCallback(bytes32 requestId) - internal - recordChainlinkFulfillment(requestId) - // solhint-disable-next-line no-empty-blocks - { - - } - - /** - * @dev Reverts if the sender is not the oracle of the request. - * Emits ChainlinkFulfilled event. - * @param requestId The request ID for fulfillment - */ - modifier recordChainlinkFulfillment(bytes32 requestId) { - require(msg.sender == s_pendingRequests[requestId], "Source must be the oracle of the request"); - delete s_pendingRequests[requestId]; - emit ChainlinkFulfilled(requestId); - _; - } - - /** - * @dev Reverts if the request is already pending - * @param requestId The request ID for fulfillment - */ - modifier notPendingRequest(bytes32 requestId) { - require(s_pendingRequests[requestId] == address(0), "Request is already pending"); - _; - } -} diff --git a/contracts/src/v0.7/ConfirmedOwner.sol b/contracts/src/v0.7/ConfirmedOwner.sol deleted file mode 100644 index a411ba8ee58..00000000000 --- a/contracts/src/v0.7/ConfirmedOwner.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./ConfirmedOwnerWithProposal.sol"; - -/** - * @title The ConfirmedOwner contract - * @notice A contract with helpers for basic contract ownership. - */ -contract ConfirmedOwner is ConfirmedOwnerWithProposal { - constructor(address newOwner) ConfirmedOwnerWithProposal(newOwner, address(0)) {} -} diff --git a/contracts/src/v0.7/ConfirmedOwnerWithProposal.sol b/contracts/src/v0.7/ConfirmedOwnerWithProposal.sol deleted file mode 100644 index b95c1711db7..00000000000 --- a/contracts/src/v0.7/ConfirmedOwnerWithProposal.sol +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./interfaces/OwnableInterface.sol"; - -/** - * @title The ConfirmedOwner contract - * @notice A contract with helpers for basic contract ownership. - */ -contract ConfirmedOwnerWithProposal is OwnableInterface { - address private s_owner; - address private s_pendingOwner; - - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - - constructor(address newOwner, address pendingOwner) { - require(newOwner != address(0), "Cannot set owner to zero"); - - s_owner = newOwner; - if (pendingOwner != address(0)) { - _transferOwnership(pendingOwner); - } - } - - /** - * @notice Allows an owner to begin transferring ownership to a new address, - * pending. - */ - function transferOwnership(address to) public override onlyOwner { - _transferOwnership(to); - } - - /** - * @notice Allows an ownership transfer to be completed by the recipient. - */ - function acceptOwnership() external override { - require(msg.sender == s_pendingOwner, "Must be proposed owner"); - - address oldOwner = s_owner; - s_owner = msg.sender; - s_pendingOwner = address(0); - - emit OwnershipTransferred(oldOwner, msg.sender); - } - - /** - * @notice Get the current owner - */ - function owner() public view override returns (address) { - return s_owner; - } - - /** - * @notice validate, transfer ownership, and emit relevant events - */ - function _transferOwnership(address to) private { - require(to != msg.sender, "Cannot transfer to self"); - - s_pendingOwner = to; - - emit OwnershipTransferRequested(s_owner, to); - } - - /** - * @notice validate access - */ - function _validateOwnership() internal view { - require(msg.sender == s_owner, "Only callable by owner"); - } - - /** - * @notice Reverts if called by anyone other than the contract owner. - */ - modifier onlyOwner() { - _validateOwnership(); - _; - } -} diff --git a/contracts/src/v0.7/Denominations.sol b/contracts/src/v0.7/Denominations.sol deleted file mode 100644 index 54556db8e8f..00000000000 --- a/contracts/src/v0.7/Denominations.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -library Denominations { - address public constant ETH = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; - address public constant BTC = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB; - - // Fiat currencies follow https://en.wikipedia.org/wiki/ISO_4217 - address public constant USD = address(840); - address public constant GBP = address(826); - address public constant EUR = address(978); - address public constant JPY = address(392); - address public constant KRW = address(410); - address public constant CNY = address(156); - address public constant AUD = address(36); - address public constant CAD = address(124); - address public constant CHF = address(756); - address public constant ARS = address(32); - address public constant PHP = address(608); - address public constant NZD = address(554); - address public constant SGD = address(702); - address public constant NGN = address(566); - address public constant ZAR = address(710); - address public constant RUB = address(643); - address public constant INR = address(356); - address public constant BRL = address(986); -} diff --git a/contracts/src/v0.7/KeeperBase.sol b/contracts/src/v0.7/KeeperBase.sol deleted file mode 100644 index 6af11a8eab9..00000000000 --- a/contracts/src/v0.7/KeeperBase.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract KeeperBase { - /** - * @notice method that allows it to be simulated via eth_call by checking that - * the sender is the zero address. - */ - function preventExecution() internal view { - require(tx.origin == address(0), "only for simulated backend"); - } - - /** - * @notice modifier that allows it to be simulated via eth_call by checking - * that the sender is the zero address. - */ - modifier cannotExecute() { - preventExecution(); - _; - } -} diff --git a/contracts/src/v0.7/KeeperCompatible.sol b/contracts/src/v0.7/KeeperCompatible.sol deleted file mode 100644 index 9780eb64f7a..00000000000 --- a/contracts/src/v0.7/KeeperCompatible.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./KeeperBase.sol"; -import "./interfaces/KeeperCompatibleInterface.sol"; - -abstract contract KeeperCompatible is KeeperBase, KeeperCompatibleInterface {} diff --git a/contracts/src/v0.7/KeeperRegistry1_1.sol b/contracts/src/v0.7/KeeperRegistry1_1.sol deleted file mode 100644 index d61ada83e01..00000000000 --- a/contracts/src/v0.7/KeeperRegistry1_1.sol +++ /dev/null @@ -1,834 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./interfaces/AggregatorV3Interface.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/KeeperCompatibleInterface.sol"; -import "./interfaces/KeeperRegistryInterface.sol"; -import "./interfaces/TypeAndVersionInterface.sol"; -import "./vendor/SafeMathChainlink.sol"; -import "./vendor/Address.sol"; -import "./vendor/Pausable.sol"; -import "./vendor/ReentrancyGuard.sol"; -import "./vendor/SignedSafeMath.sol"; -import "./vendor/SafeMath96.sol"; -import "./KeeperBase.sol"; -import "./ConfirmedOwner.sol"; - -/** - * @notice Registry for adding work for Chainlink Keepers to perform on client - * contracts. Clients must support the Upkeep interface. - */ -contract KeeperRegistry1_1 is - TypeAndVersionInterface, - ConfirmedOwner, - KeeperBase, - ReentrancyGuard, - Pausable, - KeeperRegistryExecutableInterface -{ - using Address for address; - using SafeMathChainlink for uint256; - using SafeMath96 for uint96; - using SignedSafeMath for int256; - - address private constant ZERO_ADDRESS = address(0); - address private constant IGNORE_ADDRESS = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF; - bytes4 private constant CHECK_SELECTOR = KeeperCompatibleInterface.checkUpkeep.selector; - bytes4 private constant PERFORM_SELECTOR = KeeperCompatibleInterface.performUpkeep.selector; - uint256 private constant CALL_GAS_MAX = 5_000_000; - uint256 private constant CALL_GAS_MIN = 2_300; - uint256 private constant CANCELATION_DELAY = 50; - uint256 private constant CUSHION = 5_000; - uint256 private constant REGISTRY_GAS_OVERHEAD = 80_000; - uint256 private constant PPB_BASE = 1_000_000_000; - uint64 private constant UINT64_MAX = 2**64 - 1; - uint96 private constant LINK_TOTAL_SUPPLY = 1e27; - - uint256 private s_upkeepCount; - uint256[] private s_canceledUpkeepList; - address[] private s_keeperList; - mapping(uint256 => Upkeep) private s_upkeep; - mapping(address => KeeperInfo) private s_keeperInfo; - mapping(address => address) private s_proposedPayee; - mapping(uint256 => bytes) private s_checkData; - Config private s_config; - uint256 private s_fallbackGasPrice; // not in config object for gas savings - uint256 private s_fallbackLinkPrice; // not in config object for gas savings - uint256 private s_expectedLinkBalance; - - LinkTokenInterface public immutable LINK; - AggregatorV3Interface public immutable LINK_ETH_FEED; - AggregatorV3Interface public immutable FAST_GAS_FEED; - - address private s_registrar; - - /** - * @notice versions: - * - KeeperRegistry 1.1.0: added flatFeeMicroLink - * - KeeperRegistry 1.0.0: initial release - */ - string public constant override typeAndVersion = "KeeperRegistry 1.1.0"; - - struct Upkeep { - address target; - uint32 executeGas; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - address lastKeeper; - } - - struct KeeperInfo { - address payee; - uint96 balance; - bool active; - } - - struct Config { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - } - - struct PerformParams { - address from; - uint256 id; - bytes performData; - uint256 maxLinkPayment; - uint256 gasLimit; - uint256 adjustedGasWei; - uint256 linkEth; - } - - event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - address indexed from, - uint96 payment, - bytes performData - ); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event ConfigSet( - uint32 paymentPremiumPPB, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ); - event FlatFeeSet(uint32 flatFeeMicroLink); - event KeepersUpdated(address[] keepers, address[] payees); - event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); - event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); - event RegistrarChanged(address indexed from, address indexed to); - - /** - * @param link address of the LINK Token - * @param linkEthFeed address of the LINK/ETH price feed - * @param fastGasFeed address of the Fast Gas price feed - * @param paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @param flatFeeMicroLink flat fee paid to oracles for performing upkeeps, - * priced in MicroLink; can be used in conjunction with or independently of - * paymentPremiumPPB - * @param blockCountPerTurn number of blocks each oracle has during their turn to - * perform upkeep before it will be the next keeper's turn to submit - * @param checkGasLimit gas limit when checking for upkeep - * @param stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @param gasCeilingMultiplier multiplier to apply to the fast gas feed price - * when calculating the payment ceiling for keepers - * @param fallbackGasPrice gas price used if the gas price feed is stale - * @param fallbackLinkPrice LINK price used if the LINK price feed is stale - */ - constructor( - address link, - address linkEthFeed, - address fastGasFeed, - uint32 paymentPremiumPPB, - uint32 flatFeeMicroLink, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(link); - LINK_ETH_FEED = AggregatorV3Interface(linkEthFeed); - FAST_GAS_FEED = AggregatorV3Interface(fastGasFeed); - - setConfig( - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - fallbackGasPrice, - fallbackLinkPrice - ); - } - - // ACTIONS - - /** - * @notice adds a new upkeep - * @param target address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when - * performing upkeep - * @param admin address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - */ - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external override onlyOwnerOrRegistrar returns (uint256 id) { - require(target.isContract(), "target is not a contract"); - require(gasLimit >= CALL_GAS_MIN, "min gas is 2300"); - require(gasLimit <= CALL_GAS_MAX, "max gas is 5000000"); - - id = s_upkeepCount; - s_upkeep[id] = Upkeep({ - target: target, - executeGas: gasLimit, - balance: 0, - admin: admin, - maxValidBlocknumber: UINT64_MAX, - lastKeeper: address(0) - }); - s_checkData[id] = checkData; - s_upkeepCount++; - - emit UpkeepRegistered(id, gasLimit, admin); - - return id; - } - - /** - * @notice simulated by keepers via eth_call to see if the upkeep needs to be - * performed. If upkeep is needed, the call then simulates performUpkeep - * to make sure it succeeds. Finally, it returns the success status along with - * payment information and the perform data payload. - * @param id identifier of the upkeep to check - * @param from the address to simulate performing the upkeep from - */ - function checkUpkeep(uint256 id, address from) - external - override - whenNotPaused - cannotExecute - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) - { - Upkeep memory upkeep = s_upkeep[id]; - - bytes memory callData = abi.encodeWithSelector(CHECK_SELECTOR, s_checkData[id]); - (bool success, bytes memory result) = upkeep.target.call{gas: s_config.checkGasLimit}(callData); - - if (!success) { - string memory upkeepRevertReason = getRevertMsg(result); - string memory reason = string(abi.encodePacked("call to check target failed: ", upkeepRevertReason)); - revert(reason); - } - - (success, performData) = abi.decode(result, (bool, bytes)); - require(success, "upkeep not needed"); - - PerformParams memory params = generatePerformParams(from, id, performData, false); - prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - return (performData, params.maxLinkPayment, params.gasLimit, params.adjustedGasWei, params.linkEth); - } - - /** - * @notice executes the upkeep with the perform data returned from - * checkUpkeep, validates the keeper's permissions, and pays the keeper. - * @param id identifier of the upkeep to execute the data with. - * @param performData calldata parameter to be passed to the target upkeep. - */ - function performUpkeep(uint256 id, bytes calldata performData) external override returns (bool success) { - return performUpkeepWithParams(generatePerformParams(msg.sender, id, performData, true)); - } - - /** - * @notice prevent an upkeep from being performed in the future - * @param id upkeep to be canceled - */ - function cancelUpkeep(uint256 id) external override { - uint64 maxValid = s_upkeep[id].maxValidBlocknumber; - bool notCanceled = maxValid == UINT64_MAX; - bool isOwner = msg.sender == owner(); - require(notCanceled || (isOwner && maxValid > block.number), "too late to cancel upkeep"); - require(isOwner || msg.sender == s_upkeep[id].admin, "only owner or admin"); - - uint256 height = block.number; - if (!isOwner) { - height = height.add(CANCELATION_DELAY); - } - s_upkeep[id].maxValidBlocknumber = uint64(height); - if (notCanceled) { - s_canceledUpkeepList.push(id); - } - - emit UpkeepCanceled(id, uint64(height)); - } - - /** - * @notice adds LINK funding for an upkeep by transferring from the sender's - * LINK balance - * @param id upkeep to fund - * @param amount number of LINK to transfer - */ - function addFunds(uint256 id, uint96 amount) external override { - require(s_upkeep[id].maxValidBlocknumber == UINT64_MAX, "upkeep must be active"); - s_upkeep[id].balance = s_upkeep[id].balance.add(amount); - s_expectedLinkBalance = s_expectedLinkBalance.add(amount); - LINK.transferFrom(msg.sender, address(this), amount); - emit FundsAdded(id, msg.sender, amount); - } - - /** - * @notice uses LINK's transferAndCall to LINK and add funding to an upkeep - * @dev safe to cast uint256 to uint96 as total LINK supply is under UINT96MAX - * @param sender the account which transferred the funds - * @param amount number of LINK transfer - */ - function onTokenTransfer( - address sender, - uint256 amount, - bytes calldata data - ) external { - require(msg.sender == address(LINK), "only callable through LINK"); - require(data.length == 32, "data must be 32 bytes"); - uint256 id = abi.decode(data, (uint256)); - require(s_upkeep[id].maxValidBlocknumber == UINT64_MAX, "upkeep must be active"); - - s_upkeep[id].balance = s_upkeep[id].balance.add(uint96(amount)); - s_expectedLinkBalance = s_expectedLinkBalance.add(amount); - - emit FundsAdded(id, sender, uint96(amount)); - } - - /** - * @notice removes funding from a canceled upkeep - * @param id upkeep to withdraw funds from - * @param to destination address for sending remaining funds - */ - function withdrawFunds(uint256 id, address to) external validateRecipient(to) { - require(s_upkeep[id].admin == msg.sender, "only callable by admin"); - require(s_upkeep[id].maxValidBlocknumber <= block.number, "upkeep must be canceled"); - - uint256 amount = s_upkeep[id].balance; - s_upkeep[id].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance.sub(amount); - emit FundsWithdrawn(id, amount, to); - - LINK.transfer(to, amount); - } - - /** - * @notice recovers LINK funds improperly transferred to the registry - * @dev In principle this function’s execution cost could exceed block - * gas limit. However, in our anticipated deployment, the number of upkeeps and - * keepers will be low enough to avoid this problem. - */ - function recoverFunds() external onlyOwner { - uint256 total = LINK.balanceOf(address(this)); - LINK.transfer(msg.sender, total.sub(s_expectedLinkBalance)); - } - - /** - * @notice withdraws a keeper's payment, callable only by the keeper's payee - * @param from keeper address - * @param to address to send the payment to - */ - function withdrawPayment(address from, address to) external validateRecipient(to) { - KeeperInfo memory keeper = s_keeperInfo[from]; - require(keeper.payee == msg.sender, "only callable by payee"); - - s_keeperInfo[from].balance = 0; - s_expectedLinkBalance = s_expectedLinkBalance.sub(keeper.balance); - emit PaymentWithdrawn(from, keeper.balance, to, msg.sender); - - LINK.transfer(to, keeper.balance); - } - - /** - * @notice proposes the safe transfer of a keeper's payee to another address - * @param keeper address of the keeper to transfer payee role - * @param proposed address to nominate for next payeeship - */ - function transferPayeeship(address keeper, address proposed) external { - require(s_keeperInfo[keeper].payee == msg.sender, "only callable by payee"); - require(proposed != msg.sender, "cannot transfer to self"); - - if (s_proposedPayee[keeper] != proposed) { - s_proposedPayee[keeper] = proposed; - emit PayeeshipTransferRequested(keeper, msg.sender, proposed); - } - } - - /** - * @notice accepts the safe transfer of payee role for a keeper - * @param keeper address to accept the payee role for - */ - function acceptPayeeship(address keeper) external { - require(s_proposedPayee[keeper] == msg.sender, "only callable by proposed payee"); - address past = s_keeperInfo[keeper].payee; - s_keeperInfo[keeper].payee = msg.sender; - s_proposedPayee[keeper] = ZERO_ADDRESS; - - emit PayeeshipTransferred(keeper, past, msg.sender); - } - - /** - * @notice signals to keepers that they should not perform upkeeps until the - * contract has been unpaused - */ - function pause() external onlyOwner { - _pause(); - } - - /** - * @notice signals to keepers that they can perform upkeeps once again after - * having been paused - */ - function unpause() external onlyOwner { - _unpause(); - } - - // SETTERS - - /** - * @notice updates the configuration of the registry - * @param paymentPremiumPPB payment premium rate oracles receive on top of - * being reimbursed for gas, measured in parts per billion - * @param flatFeeMicroLink flat fee paid to oracles for performing upkeeps - * @param blockCountPerTurn number of blocks an oracle should wait before - * checking for upkeep - * @param checkGasLimit gas limit when checking for upkeep - * @param stalenessSeconds number of seconds that is allowed for feed data to - * be stale before switching to the fallback pricing - * @param fallbackGasPrice gas price used if the gas price feed is stale - * @param fallbackLinkPrice LINK price used if the LINK price feed is stale - */ - function setConfig( - uint32 paymentPremiumPPB, - uint32 flatFeeMicroLink, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ) public onlyOwner { - s_config = Config({ - paymentPremiumPPB: paymentPremiumPPB, - flatFeeMicroLink: flatFeeMicroLink, - blockCountPerTurn: blockCountPerTurn, - checkGasLimit: checkGasLimit, - stalenessSeconds: stalenessSeconds, - gasCeilingMultiplier: gasCeilingMultiplier - }); - s_fallbackGasPrice = fallbackGasPrice; - s_fallbackLinkPrice = fallbackLinkPrice; - - emit ConfigSet( - paymentPremiumPPB, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - fallbackGasPrice, - fallbackLinkPrice - ); - emit FlatFeeSet(flatFeeMicroLink); - } - - /** - * @notice update the list of keepers allowed to perform upkeep - * @param keepers list of addresses allowed to perform upkeep - * @param payees addresses corresponding to keepers who are allowed to - * move payments which have been accrued - */ - function setKeepers(address[] calldata keepers, address[] calldata payees) external onlyOwner { - require(keepers.length == payees.length, "address lists not the same length"); - require(keepers.length >= 2, "not enough keepers"); - for (uint256 i = 0; i < s_keeperList.length; i++) { - address keeper = s_keeperList[i]; - s_keeperInfo[keeper].active = false; - } - for (uint256 i = 0; i < keepers.length; i++) { - address keeper = keepers[i]; - KeeperInfo storage s_keeper = s_keeperInfo[keeper]; - address oldPayee = s_keeper.payee; - address newPayee = payees[i]; - require(newPayee != address(0), "cannot set payee to the zero address"); - require(oldPayee == ZERO_ADDRESS || oldPayee == newPayee || newPayee == IGNORE_ADDRESS, "cannot change payee"); - require(!s_keeper.active, "cannot add keeper twice"); - s_keeper.active = true; - if (newPayee != IGNORE_ADDRESS) { - s_keeper.payee = newPayee; - } - } - s_keeperList = keepers; - emit KeepersUpdated(keepers, payees); - } - - /** - * @notice update registrar - * @param registrar new registrar - */ - function setRegistrar(address registrar) external onlyOwnerOrRegistrar { - address previous = s_registrar; - require(registrar != previous, "Same registrar"); - s_registrar = registrar; - emit RegistrarChanged(previous, registrar); - } - - // GETTERS - - /** - * @notice read all of the details about an upkeep - */ - function getUpkeep(uint256 id) - external - view - override - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber - ) - { - Upkeep memory reg = s_upkeep[id]; - return ( - reg.target, - reg.executeGas, - s_checkData[id], - reg.balance, - reg.lastKeeper, - reg.admin, - reg.maxValidBlocknumber - ); - } - - /** - * @notice read the total number of upkeep's registered - */ - function getUpkeepCount() external view override returns (uint256) { - return s_upkeepCount; - } - - /** - * @notice read the current list canceled upkeep IDs - */ - function getCanceledUpkeepList() external view override returns (uint256[] memory) { - return s_canceledUpkeepList; - } - - /** - * @notice read the current list of addresses allowed to perform upkeep - */ - function getKeeperList() external view override returns (address[] memory) { - return s_keeperList; - } - - /** - * @notice read the current registrar - */ - function getRegistrar() external view returns (address) { - return s_registrar; - } - - /** - * @notice read the current info about any keeper address - */ - function getKeeperInfo(address query) - external - view - override - returns ( - address payee, - bool active, - uint96 balance - ) - { - KeeperInfo memory keeper = s_keeperInfo[query]; - return (keeper.payee, keeper.active, keeper.balance); - } - - /** - * @notice read the current configuration of the registry - */ - function getConfig() - external - view - override - returns ( - uint32 paymentPremiumPPB, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ) - { - Config memory config = s_config; - return ( - config.paymentPremiumPPB, - config.blockCountPerTurn, - config.checkGasLimit, - config.stalenessSeconds, - config.gasCeilingMultiplier, - s_fallbackGasPrice, - s_fallbackLinkPrice - ); - } - - /** - * @notice getFlatFee gets the flat rate fee charged to customers when performing upkeep, - * in units of of micro LINK - */ - function getFlatFee() external view returns (uint32) { - return s_config.flatFeeMicroLink; - } - - /** - * @notice calculates the minimum balance required for an upkeep to remain eligible - */ - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96 minBalance) { - return getMaxPaymentForGas(s_upkeep[id].executeGas); - } - - /** - * @notice calculates the maximum payment for a given gas limit - */ - function getMaxPaymentForGas(uint256 gasLimit) public view returns (uint96 maxPayment) { - (uint256 gasWei, uint256 linkEth) = getFeedData(); - uint256 adjustedGasWei = adjustGasPrice(gasWei, false); - return calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); - } - - // PRIVATE - - /** - * @dev retrieves feed data for fast gas/eth and link/eth prices. if the feed - * data is stale it uses the configured fallback price. Once a price is picked - * for gas it takes the min of gas price in the transaction or the fast gas - * price in order to reduce costs for the upkeep clients. - */ - function getFeedData() private view returns (uint256 gasWei, uint256 linkEth) { - uint32 stalenessSeconds = s_config.stalenessSeconds; - bool staleFallback = stalenessSeconds > 0; - uint256 timestamp; - int256 feedValue; - (, feedValue, , timestamp, ) = FAST_GAS_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - gasWei = s_fallbackGasPrice; - } else { - gasWei = uint256(feedValue); - } - (, feedValue, , timestamp, ) = LINK_ETH_FEED.latestRoundData(); - if ((staleFallback && stalenessSeconds < block.timestamp - timestamp) || feedValue <= 0) { - linkEth = s_fallbackLinkPrice; - } else { - linkEth = uint256(feedValue); - } - return (gasWei, linkEth); - } - - /** - * @dev calculates LINK paid for gas spent plus a configure premium percentage - */ - function calculatePaymentAmount( - uint256 gasLimit, - uint256 gasWei, - uint256 linkEth - ) private view returns (uint96 payment) { - Config memory config = s_config; - uint256 weiForGas = gasWei.mul(gasLimit.add(REGISTRY_GAS_OVERHEAD)); - uint256 premium = PPB_BASE.add(config.paymentPremiumPPB); - uint256 total = weiForGas.mul(1e9).mul(premium).div(linkEth).add(uint256(config.flatFeeMicroLink).mul(1e12)); - require(total <= LINK_TOTAL_SUPPLY, "payment greater than all LINK"); - return uint96(total); // LINK_TOTAL_SUPPLY < UINT96_MAX - } - - /** - * @dev calls target address with exactly gasAmount gas and data as calldata - * or reverts if at least gasAmount gas is not available - */ - function callWithExactGas( - uint256 gasAmount, - address target, - bytes memory data - ) private returns (bool success) { - assembly { - let g := gas() - // Compute g -= CUSHION and check for underflow - if lt(g, CUSHION) { - revert(0, 0) - } - g := sub(g, CUSHION) - // if g - g//64 <= gasAmount, revert - // (we subtract g//64 because of EIP-150) - if iszero(gt(sub(g, div(g, 64)), gasAmount)) { - revert(0, 0) - } - // solidity calls check that a contract actually exists at the destination, so we do the same - if iszero(extcodesize(target)) { - revert(0, 0) - } - // call and return whether we succeeded. ignore return data - success := call(gasAmount, target, 0, add(data, 0x20), mload(data), 0, 0) - } - return success; - } - - /** - * @dev calls the Upkeep target with the performData param passed in by the - * keeper and the exact gas required by the Upkeep - */ - function performUpkeepWithParams(PerformParams memory params) - private - nonReentrant - validUpkeep(params.id) - returns (bool success) - { - Upkeep memory upkeep = s_upkeep[params.id]; - prePerformUpkeep(upkeep, params.from, params.maxLinkPayment); - - uint256 gasUsed = gasleft(); - bytes memory callData = abi.encodeWithSelector(PERFORM_SELECTOR, params.performData); - success = callWithExactGas(params.gasLimit, upkeep.target, callData); - gasUsed = gasUsed - gasleft(); - - uint96 payment = calculatePaymentAmount(gasUsed, params.adjustedGasWei, params.linkEth); - - uint96 newUpkeepBalance = s_upkeep[params.id].balance.sub(payment); - s_upkeep[params.id].balance = newUpkeepBalance; - s_upkeep[params.id].lastKeeper = params.from; - - uint96 newKeeperBalance = s_keeperInfo[params.from].balance.add(payment); - s_keeperInfo[params.from].balance = newKeeperBalance; - - emit UpkeepPerformed(params.id, success, params.from, payment, params.performData); - return success; - } - - /** - * @dev ensures a upkeep is valid - */ - function validateUpkeep(uint256 id) private view { - require(s_upkeep[id].maxValidBlocknumber > block.number, "invalid upkeep id"); - } - - /** - * @dev ensures all required checks are passed before an upkeep is performed - */ - function prePerformUpkeep( - Upkeep memory upkeep, - address from, - uint256 maxLinkPayment - ) private view { - require(s_keeperInfo[from].active, "only active keepers"); - require(upkeep.balance >= maxLinkPayment, "insufficient funds"); - require(upkeep.lastKeeper != from, "keepers must take turns"); - } - - /** - * @dev adjusts the gas price to min(ceiling, tx.gasprice) or just uses the ceiling if tx.gasprice is disabled - */ - function adjustGasPrice(uint256 gasWei, bool useTxGasPrice) private view returns (uint256 adjustedPrice) { - adjustedPrice = gasWei.mul(s_config.gasCeilingMultiplier); - if (useTxGasPrice && tx.gasprice < adjustedPrice) { - adjustedPrice = tx.gasprice; - } - } - - /** - * @dev generates a PerformParams struct for use in performUpkeepWithParams() - */ - function generatePerformParams( - address from, - uint256 id, - bytes memory performData, - bool useTxGasPrice - ) private view returns (PerformParams memory) { - uint256 gasLimit = s_upkeep[id].executeGas; - (uint256 gasWei, uint256 linkEth) = getFeedData(); - uint256 adjustedGasWei = adjustGasPrice(gasWei, useTxGasPrice); - uint96 maxLinkPayment = calculatePaymentAmount(gasLimit, adjustedGasWei, linkEth); - - return - PerformParams({ - from: from, - id: id, - performData: performData, - maxLinkPayment: maxLinkPayment, - gasLimit: gasLimit, - adjustedGasWei: adjustedGasWei, - linkEth: linkEth - }); - } - - /** - * @dev extracts a revert reason from a call result payload - */ - function getRevertMsg(bytes memory _payload) private pure returns (string memory) { - if (_payload.length < 68) return "transaction reverted silently"; - assembly { - _payload := add(_payload, 0x04) - } - return abi.decode(_payload, (string)); - } - - // MODIFIERS - - /** - * @dev ensures a upkeep is valid - */ - modifier validUpkeep(uint256 id) { - validateUpkeep(id); - _; - } - - /** - * @dev ensures that burns don't accidentally happen by sending to the zero - * address - */ - modifier validateRecipient(address to) { - require(to != address(0), "cannot send to zero address"); - _; - } - - /** - * @dev Reverts if called by anyone other than the contract owner or registrar. - */ - modifier onlyOwnerOrRegistrar() { - require(msg.sender == owner() || msg.sender == s_registrar, "Only callable by owner or registrar"); - _; - } -} diff --git a/contracts/src/v0.7/KeeperRegistry1_1Mock.sol b/contracts/src/v0.7/KeeperRegistry1_1Mock.sol deleted file mode 100644 index 3acbfb5e7af..00000000000 --- a/contracts/src/v0.7/KeeperRegistry1_1Mock.sol +++ /dev/null @@ -1,351 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract KeeperRegistry1_1Mock { - event ConfigSet( - uint32 paymentPremiumPPB, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ); - event FlatFeeSet(uint32 flatFeeMicroLink); - event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); - event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); - event KeepersUpdated(address[] keepers, address[] payees); - event OwnershipTransferRequested(address indexed from, address indexed to); - event OwnershipTransferred(address indexed from, address indexed to); - event Paused(address account); - event PayeeshipTransferRequested(address indexed keeper, address indexed from, address indexed to); - event PayeeshipTransferred(address indexed keeper, address indexed from, address indexed to); - event PaymentWithdrawn(address indexed keeper, uint256 indexed amount, address indexed to, address payee); - event RegistrarChanged(address indexed from, address indexed to); - event Unpaused(address account); - event UpkeepCanceled(uint256 indexed id, uint64 indexed atBlockHeight); - event UpkeepPerformed( - uint256 indexed id, - bool indexed success, - address indexed from, - uint96 payment, - bytes performData - ); - event UpkeepRegistered(uint256 indexed id, uint32 executeGas, address admin); - - function emitConfigSet( - uint32 paymentPremiumPPB, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ) public { - emit ConfigSet( - paymentPremiumPPB, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - fallbackGasPrice, - fallbackLinkPrice - ); - } - - function emitFlatFeeSet(uint32 flatFeeMicroLink) public { - emit FlatFeeSet(flatFeeMicroLink); - } - - function emitFundsAdded(uint256 id, address from, uint96 amount) public { - emit FundsAdded(id, from, amount); - } - - function emitFundsWithdrawn(uint256 id, uint256 amount, address to) public { - emit FundsWithdrawn(id, amount, to); - } - - function emitKeepersUpdated(address[] memory keepers, address[] memory payees) public { - emit KeepersUpdated(keepers, payees); - } - - function emitOwnershipTransferRequested(address from, address to) public { - emit OwnershipTransferRequested(from, to); - } - - function emitOwnershipTransferred(address from, address to) public { - emit OwnershipTransferred(from, to); - } - - function emitPaused(address account) public { - emit Paused(account); - } - - function emitPayeeshipTransferRequested(address keeper, address from, address to) public { - emit PayeeshipTransferRequested(keeper, from, to); - } - - function emitPayeeshipTransferred(address keeper, address from, address to) public { - emit PayeeshipTransferred(keeper, from, to); - } - - function emitPaymentWithdrawn(address keeper, uint256 amount, address to, address payee) public { - emit PaymentWithdrawn(keeper, amount, to, payee); - } - - function emitRegistrarChanged(address from, address to) public { - emit RegistrarChanged(from, to); - } - - function emitUnpaused(address account) public { - emit Unpaused(account); - } - - function emitUpkeepCanceled(uint256 id, uint64 atBlockHeight) public { - emit UpkeepCanceled(id, atBlockHeight); - } - - function emitUpkeepPerformed( - uint256 id, - bool success, - address from, - uint96 payment, - bytes memory performData - ) public { - emit UpkeepPerformed(id, success, from, payment, performData); - } - - function emitUpkeepRegistered(uint256 id, uint32 executeGas, address admin) public { - emit UpkeepRegistered(id, executeGas, admin); - } - - uint256 private s_upkeepCount; - - // Function to set the current number of registered upkeeps - function setUpkeepCount(uint256 _upkeepCount) external { - s_upkeepCount = _upkeepCount; - } - - // Function to get the current number of registered upkeeps - function getUpkeepCount() external view returns (uint256) { - return s_upkeepCount; - } - - uint256[] private s_canceledUpkeepList; - - // Function to set the current number of canceled upkeeps - function setCanceledUpkeepList(uint256[] memory _canceledUpkeepList) external { - s_canceledUpkeepList = _canceledUpkeepList; - } - - // Function to set the current number of canceled upkeeps - function getCanceledUpkeepList() external view returns (uint256[] memory) { - return s_canceledUpkeepList; - } - - address[] private s_keeperList; - - // Function to set the keeper list for testing purposes - function setKeeperList(address[] memory _keepers) external { - s_keeperList = _keepers; - } - - // Function to get the keeper list - function getKeeperList() external view returns (address[] memory) { - return s_keeperList; - } - - struct Config { - uint32 paymentPremiumPPB; - uint32 flatFeeMicroLink; // min 0.000001 LINK, max 4294 LINK - uint24 blockCountPerTurn; - uint32 checkGasLimit; - uint24 stalenessSeconds; - uint16 gasCeilingMultiplier; - } - - Config private s_config; - uint256 private s_fallbackGasPrice; - uint256 private s_fallbackLinkPrice; - - // Function to set the configuration for testing purposes - function setConfig( - uint32 _paymentPremiumPPB, - uint32 _flatFeeMicroLink, - uint24 _blockCountPerTurn, - uint32 _checkGasLimit, - uint24 _stalenessSeconds, - uint16 _gasCeilingMultiplier, - uint256 _fallbackGasPrice, - uint256 _fallbackLinkPrice - ) external { - s_config.paymentPremiumPPB = _paymentPremiumPPB; - s_config.flatFeeMicroLink = _flatFeeMicroLink; - s_config.blockCountPerTurn = _blockCountPerTurn; - s_config.checkGasLimit = _checkGasLimit; - s_config.stalenessSeconds = _stalenessSeconds; - s_config.gasCeilingMultiplier = _gasCeilingMultiplier; - s_fallbackGasPrice = _fallbackGasPrice; - s_fallbackLinkPrice = _fallbackLinkPrice; - } - - // Function to get the configuration - function getConfig() - external - view - returns ( - uint32 paymentPremiumPPB, - uint24 blockCountPerTurn, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ) - { - return ( - s_config.paymentPremiumPPB, - s_config.blockCountPerTurn, - s_config.checkGasLimit, - s_config.stalenessSeconds, - s_config.gasCeilingMultiplier, - s_fallbackGasPrice, - s_fallbackLinkPrice - ); - } - - struct Upkeep { - address target; - uint32 executeGas; - uint96 balance; - address admin; - uint64 maxValidBlocknumber; - address lastKeeper; - } - - mapping(uint256 => Upkeep) private s_upkeep; - mapping(uint256 => bytes) private s_checkData; - - // Function to set the upkeep and checkData for testing purposes - function setUpkeep( - uint256 id, - address _target, - uint32 _executeGas, - uint96 _balance, - address _admin, - uint64 _maxValidBlocknumber, - address _lastKeeper, - bytes memory _checkData - ) external { - Upkeep memory upkeep = Upkeep({ - target: _target, - executeGas: _executeGas, - balance: _balance, - admin: _admin, - maxValidBlocknumber: _maxValidBlocknumber, - lastKeeper: _lastKeeper - }); - - s_upkeep[id] = upkeep; - s_checkData[id] = _checkData; - } - - // Function to get the upkeep and checkData - function getUpkeep( - uint256 id - ) - external - view - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber - ) - { - Upkeep memory reg = s_upkeep[id]; - return ( - reg.target, - reg.executeGas, - s_checkData[id], - reg.balance, - reg.lastKeeper, - reg.admin, - reg.maxValidBlocknumber - ); - } - - mapping(uint256 => uint96) private s_minBalances; - - // Function to set the minimum balance for a specific upkeep id - function setMinBalance(uint256 id, uint96 minBalance) external { - s_minBalances[id] = minBalance; - } - - // Function to get the minimum balance for a specific upkeep id - function getMinBalanceForUpkeep(uint256 id) external view returns (uint96) { - return s_minBalances[id]; - } - - struct UpkeepData { - bytes performData; - uint256 maxLinkPayment; - uint256 gasLimit; - uint256 adjustedGasWei; - uint256 linkEth; - } - - mapping(uint256 => UpkeepData) private s_upkeepData; - - // Function to set mock data for the checkUpkeep function - function setCheckUpkeepData( - uint256 id, - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) external { - s_upkeepData[id] = UpkeepData({ - performData: performData, - maxLinkPayment: maxLinkPayment, - gasLimit: gasLimit, - adjustedGasWei: adjustedGasWei, - linkEth: linkEth - }); - } - - // Mock checkUpkeep function - function checkUpkeep( - uint256 id, - address from - ) - external - view - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ) - { - UpkeepData storage data = s_upkeepData[id]; - return (data.performData, data.maxLinkPayment, data.gasLimit, data.adjustedGasWei, data.linkEth); - } - - mapping(uint256 => bool) private s_upkeepSuccess; - - // Function to set mock return data for the performUpkeep function - function setPerformUpkeepSuccess(uint256 id, bool success) external { - s_upkeepSuccess[id] = success; - } - - // Mock performUpkeep function - function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success) { - return s_upkeepSuccess[id]; - } -} diff --git a/contracts/src/v0.7/LinkTokenReceiver.sol b/contracts/src/v0.7/LinkTokenReceiver.sol deleted file mode 100644 index d98cc25d843..00000000000 --- a/contracts/src/v0.7/LinkTokenReceiver.sol +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -abstract contract LinkTokenReceiver { - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @dev The data payload's first 2 words will be overwritten by the `sender` and `amount` - * values to ensure correctness. Calls oracleRequest. - * @param sender Address of the sender - * @param amount Amount of LINK sent (specified in wei) - * @param data Payload of the transaction - */ - function onTokenTransfer( - address sender, - uint256 amount, - bytes memory data - ) public validateFromLINK permittedFunctionsForLINK(data) { - assembly { - // solhint-disable-next-line avoid-low-level-calls - mstore(add(data, 36), sender) // ensure correct sender is passed - // solhint-disable-next-line avoid-low-level-calls - mstore(add(data, 68), amount) // ensure correct amount is passed - } - // solhint-disable-next-line avoid-low-level-calls - (bool success, ) = address(this).delegatecall(data); // calls oracleRequest - require(success, "Unable to create request"); - } - - function getChainlinkToken() public view virtual returns (address); - - /** - * @notice Validate the function called on token transfer - */ - function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal virtual; - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier validateFromLINK() { - require(msg.sender == getChainlinkToken(), "Must use LINK token"); - _; - } - - /** - * @dev Reverts if the given data does not begin with the `oracleRequest` function selector - * @param data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(data, 32)) - } - _validateTokenTransferAction(funcSelector, data); - _; - } -} diff --git a/contracts/src/v0.7/Operator.sol b/contracts/src/v0.7/Operator.sol deleted file mode 100644 index b61680d2ed0..00000000000 --- a/contracts/src/v0.7/Operator.sol +++ /dev/null @@ -1,580 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./AuthorizedReceiver.sol"; -import "./LinkTokenReceiver.sol"; -import "./ConfirmedOwner.sol"; -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/OperatorInterface.sol"; -import "./interfaces/OwnableInterface.sol"; -import "./interfaces/WithdrawalInterface.sol"; -import "./vendor/Address.sol"; -import "./vendor/SafeMathChainlink.sol"; - -/** - * @title The Chainlink Operator contract - * @notice Node operators can deploy this contract to fulfill requests sent to them - */ -contract Operator is AuthorizedReceiver, ConfirmedOwner, LinkTokenReceiver, OperatorInterface, WithdrawalInterface { - using Address for address; - using SafeMathChainlink for uint256; - - struct Commitment { - bytes31 paramsHash; - uint8 dataVersion; - } - - uint256 public constant getExpiryTime = 5 minutes; - uint256 private constant MAXIMUM_DATA_VERSION = 256; - uint256 private constant MINIMUM_CONSUMER_GAS_LIMIT = 400000; - uint256 private constant SELECTOR_LENGTH = 4; - uint256 private constant EXPECTED_REQUEST_WORDS = 2; - uint256 private constant MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS); - // We initialize fields to 1 instead of 0 so that the first invocation - // does not cost more gas. - uint256 private constant ONE_FOR_CONSISTENT_GAS_COST = 1; - // oracleRequest is intended for version 1, enabling single word responses - bytes4 private constant ORACLE_REQUEST_SELECTOR = this.oracleRequest.selector; - // operatorRequest is intended for version 2, enabling multi-word responses - bytes4 private constant OPERATOR_REQUEST_SELECTOR = this.operatorRequest.selector; - - LinkTokenInterface internal immutable linkToken; - mapping(bytes32 => Commitment) private s_commitments; - mapping(address => bool) private s_owned; - // Tokens sent for requests that have not been fulfilled yet - uint256 private s_tokensInEscrow = ONE_FOR_CONSISTENT_GAS_COST; - - event OracleRequest( - bytes32 indexed specId, - address requester, - bytes32 requestId, - uint256 payment, - address callbackAddr, - bytes4 callbackFunctionId, - uint256 cancelExpiration, - uint256 dataVersion, - bytes data - ); - - event CancelOracleRequest(bytes32 indexed requestId); - - event OracleResponse(bytes32 indexed requestId); - - event OwnableContractAccepted(address indexed acceptedContract); - - event TargetsUpdatedAuthorizedSenders(address[] targets, address[] senders, address changedBy); - - /** - * @notice Deploy with the address of the LINK token - * @dev Sets the LinkToken address for the imported LinkTokenInterface - * @param link The address of the LINK token - * @param owner The address of the owner - */ - constructor(address link, address owner) ConfirmedOwner(owner) { - linkToken = LinkTokenInterface(link); // external but already deployed and unalterable - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual returns (string memory) { - return "Operator 1.0.0"; - } - - /** - * @notice Creates the Chainlink request. This is a backwards compatible API - * with the Oracle.sol contract, but the behavior changes because - * callbackAddress is assumed to be the same as the request sender. - * @param callbackAddress The consumer of the request - * @param payment The amount of payment given (specified in wei) - * @param specId The Job Specification ID - * @param callbackAddress The address the oracle data will be sent to - * @param callbackFunctionId The callback function ID for the response - * @param nonce The nonce sent by the requester - * @param dataVersion The specified data version - * @param data The extra request parameters - */ - function oracleRequest( - address sender, - uint256 payment, - bytes32 specId, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external override validateFromLINK { - (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( - sender, - payment, - callbackAddress, - callbackFunctionId, - nonce, - dataVersion - ); - emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); - } - - /** - * @notice Creates the Chainlink request - * @dev Stores the hash of the params as the on-chain commitment for the request. - * Emits OracleRequest event for the Chainlink node to detect. - * @param sender The sender of the request - * @param payment The amount of payment given (specified in wei) - * @param specId The Job Specification ID - * @param callbackFunctionId The callback function ID for the response - * @param nonce The nonce sent by the requester - * @param dataVersion The specified data version - * @param data The extra request parameters - */ - function operatorRequest( - address sender, - uint256 payment, - bytes32 specId, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external override validateFromLINK { - (bytes32 requestId, uint256 expiration) = _verifyAndProcessOracleRequest( - sender, - payment, - sender, - callbackFunctionId, - nonce, - dataVersion - ); - emit OracleRequest(specId, sender, requestId, payment, sender, callbackFunctionId, expiration, dataVersion, data); - } - - /** - * @notice Called by the Chainlink node to fulfill requests - * @dev Given params must hash back to the commitment stored from `oracleRequest`. - * Will call the callback address' callback function without bubbling up error - * checking in a `require` so that the node can get paid. - * @param requestId The fulfillment request ID that must match the requester's - * @param payment The payment amount that will be released for the oracle (specified in wei) - * @param callbackAddress The callback address to call for fulfillment - * @param callbackFunctionId The callback function ID to use for fulfillment - * @param expiration The expiration that the node should respond by before the requester can cancel - * @param data The data to return to the consuming contract - * @return Status if the external call was successful - */ - function fulfillOracleRequest( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes32 data - ) - external - override - validateAuthorizedSender - validateRequestId(requestId) - validateCallbackAddress(callbackAddress) - returns (bool) - { - _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 1); - emit OracleResponse(requestId); - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = callbackAddress.call(abi.encodeWithSelector(callbackFunctionId, requestId, data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - /** - * @notice Called by the Chainlink node to fulfill requests with multi-word support - * @dev Given params must hash back to the commitment stored from `oracleRequest`. - * Will call the callback address' callback function without bubbling up error - * checking in a `require` so that the node can get paid. - * @param requestId The fulfillment request ID that must match the requester's - * @param payment The payment amount that will be released for the oracle (specified in wei) - * @param callbackAddress The callback address to call for fulfillment - * @param callbackFunctionId The callback function ID to use for fulfillment - * @param expiration The expiration that the node should respond by before the requester can cancel - * @param data The data to return to the consuming contract - * @return Status if the external call was successful - */ - function fulfillOracleRequest2( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes calldata data - ) - external - override - validateAuthorizedSender - validateRequestId(requestId) - validateCallbackAddress(callbackAddress) - validateMultiWordResponseId(requestId, data) - returns (bool) - { - _verifyOracleRequestAndProcessPayment(requestId, payment, callbackAddress, callbackFunctionId, expiration, 2); - emit OracleResponse(requestId); - require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas"); - // All updates to the oracle's fulfillment should come before calling the - // callback(addr+functionId) as it is untrusted. - // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern - (bool success, ) = callbackAddress.call(abi.encodePacked(callbackFunctionId, data)); // solhint-disable-line avoid-low-level-calls - return success; - } - - /** - * @notice Transfer the ownership of ownable contracts. This is primarily - * intended for Authorized Forwarders but could possibly be extended to work - * with future contracts. - * @param ownable list of addresses to transfer - * @param newOwner address to transfer ownership to - */ - function transferOwnableContracts(address[] calldata ownable, address newOwner) external onlyOwner { - for (uint256 i = 0; i < ownable.length; i++) { - s_owned[ownable[i]] = false; - OwnableInterface(ownable[i]).transferOwnership(newOwner); - } - } - - /** - * @notice Accept the ownership of an ownable contract. This is primarily - * intended for Authorized Forwarders but could possibly be extended to work - * with future contracts. - * @dev Must be the pending owner on the contract - * @param ownable list of addresses of Ownable contracts to accept - */ - function acceptOwnableContracts(address[] calldata ownable) public validateAuthorizedSenderSetter { - for (uint256 i = 0; i < ownable.length; i++) { - s_owned[ownable[i]] = true; - emit OwnableContractAccepted(ownable[i]); - OwnableInterface(ownable[i]).acceptOwnership(); - } - } - - /** - * @notice Sets the fulfillment permission for - * @param targets The addresses to set permissions on - * @param senders The addresses that are allowed to send updates - */ - function setAuthorizedSendersOn(address[] calldata targets, address[] calldata senders) - public - validateAuthorizedSenderSetter - { - TargetsUpdatedAuthorizedSenders(targets, senders, msg.sender); - - for (uint256 i = 0; i < targets.length; i++) { - AuthorizedReceiverInterface(targets[i]).setAuthorizedSenders(senders); - } - } - - /** - * @notice Accepts ownership of ownable contracts and then immediately sets - * the authorized sender list on each of the newly owned contracts. This is - * primarily intended for Authorized Forwarders but could possibly be - * extended to work with future contracts. - * @param targets The addresses to set permissions on - * @param senders The addresses that are allowed to send updates - */ - function acceptAuthorizedReceivers(address[] calldata targets, address[] calldata senders) - external - validateAuthorizedSenderSetter - { - acceptOwnableContracts(targets); - setAuthorizedSendersOn(targets, senders); - } - - /** - * @notice Allows the node operator to withdraw earned LINK to a given address - * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node - * @param recipient The address to send the LINK token to - * @param amount The amount to send (specified in wei) - */ - function withdraw(address recipient, uint256 amount) - external - override(OracleInterface, WithdrawalInterface) - onlyOwner - validateAvailableFunds(amount) - { - assert(linkToken.transfer(recipient, amount)); - } - - /** - * @notice Displays the amount of LINK that is available for the node operator to withdraw - * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage - * @return The amount of withdrawable LINK on the contract - */ - function withdrawable() external view override(OracleInterface, WithdrawalInterface) returns (uint256) { - return _fundsAvailable(); - } - - /** - * @notice Forward a call to another contract - * @dev Only callable by the owner - * @param to address - * @param data to forward - */ - function ownerForward(address to, bytes calldata data) external onlyOwner validateNotToLINK(to) { - require(to.isContract(), "Must forward to a contract"); - (bool status, ) = to.call(data); - require(status, "Forwarded call failed"); - } - - /** - * @notice Interact with other LinkTokenReceiver contracts by calling transferAndCall - * @param to The address to transfer to. - * @param value The amount to be transferred. - * @param data The extra data to be passed to the receiving contract. - * @return success bool - */ - function ownerTransferAndCall( - address to, - uint256 value, - bytes calldata data - ) external override onlyOwner validateAvailableFunds(value) returns (bool success) { - return linkToken.transferAndCall(to, value, data); - } - - /** - * @notice Distribute funds to multiple addresses using ETH send - * to this payable function. - * @dev Array length must be equal, ETH sent must equal the sum of amounts. - * A malicious receiver could cause the distribution to revert, in which case - * it is expected that the address is removed from the list. - * @param receivers list of addresses - * @param amounts list of amounts - */ - function distributeFunds(address payable[] calldata receivers, uint256[] calldata amounts) external payable { - require(receivers.length > 0 && receivers.length == amounts.length, "Invalid array length(s)"); - uint256 valueRemaining = msg.value; - for (uint256 i = 0; i < receivers.length; i++) { - uint256 sendAmount = amounts[i]; - valueRemaining = valueRemaining.sub(sendAmount); - receivers[i].transfer(sendAmount); - } - require(valueRemaining == 0, "Too much ETH sent"); - } - - /** - * @notice Allows recipient to cancel requests sent to this oracle contract. - * Will transfer the LINK sent for the request back to the recipient address. - * @dev Given params must hash to a commitment stored on the contract in order - * for the request to be valid. Emits CancelOracleRequest event. - * @param requestId The request ID - * @param payment The amount of payment given (specified in wei) - * @param callbackFunc The requester's specified callback function selector - * @param expiration The time of the expiration for the request - */ - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) external override { - bytes31 paramsHash = _buildParamsHash(payment, msg.sender, callbackFunc, expiration); - require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); - // solhint-disable-next-line not-rely-on-time - require(expiration <= block.timestamp, "Request is not expired"); - - delete s_commitments[requestId]; - emit CancelOracleRequest(requestId); - - linkToken.transfer(msg.sender, payment); - } - - /** - * @notice Allows requester to cancel requests sent to this oracle contract. - * Will transfer the LINK sent for the request back to the recipient address. - * @dev Given params must hash to a commitment stored on the contract in order - * for the request to be valid. Emits CancelOracleRequest event. - * @param nonce The nonce used to generate the request ID - * @param payment The amount of payment given (specified in wei) - * @param callbackFunc The requester's specified callback function selector - * @param expiration The time of the expiration for the request - */ - function cancelOracleRequestByRequester( - uint256 nonce, - uint256 payment, - bytes4 callbackFunc, - uint256 expiration - ) external { - bytes32 requestId = keccak256(abi.encodePacked(msg.sender, nonce)); - bytes31 paramsHash = _buildParamsHash(payment, msg.sender, callbackFunc, expiration); - require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); - // solhint-disable-next-line not-rely-on-time - require(expiration <= block.timestamp, "Request is not expired"); - - delete s_commitments[requestId]; - emit CancelOracleRequest(requestId); - - linkToken.transfer(msg.sender, payment); - } - - /** - * @notice Returns the address of the LINK token - * @dev This is the public implementation for chainlinkTokenAddress, which is - * an internal method of the ChainlinkClient contract - */ - function getChainlinkToken() public view override returns (address) { - return address(linkToken); - } - - /** - * @notice Require that the token transfer action is valid - * @dev OPERATOR_REQUEST_SELECTOR = multiword, ORACLE_REQUEST_SELECTOR = singleword - */ - function _validateTokenTransferAction(bytes4 funcSelector, bytes memory data) internal pure override { - require(data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length"); - require( - funcSelector == OPERATOR_REQUEST_SELECTOR || funcSelector == ORACLE_REQUEST_SELECTOR, - "Must use whitelisted functions" - ); - } - - /** - * @notice Verify the Oracle Request and record necessary information - * @param sender The sender of the request - * @param payment The amount of payment given (specified in wei) - * @param callbackAddress The callback address for the response - * @param callbackFunctionId The callback function ID for the response - * @param nonce The nonce sent by the requester - */ - function _verifyAndProcessOracleRequest( - address sender, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion - ) private validateNotToLINK(callbackAddress) returns (bytes32 requestId, uint256 expiration) { - requestId = keccak256(abi.encodePacked(sender, nonce)); - require(s_commitments[requestId].paramsHash == 0, "Must use a unique ID"); - // solhint-disable-next-line not-rely-on-time - expiration = block.timestamp.add(getExpiryTime); - bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); - s_commitments[requestId] = Commitment(paramsHash, _safeCastToUint8(dataVersion)); - s_tokensInEscrow = s_tokensInEscrow.add(payment); - return (requestId, expiration); - } - - /** - * @notice Verify the Oracle request and unlock escrowed payment - * @param requestId The fulfillment request ID that must match the requester's - * @param payment The payment amount that will be released for the oracle (specified in wei) - * @param callbackAddress The callback address to call for fulfillment - * @param callbackFunctionId The callback function ID to use for fulfillment - * @param expiration The expiration that the node should respond by before the requester can cancel - */ - function _verifyOracleRequestAndProcessPayment( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - uint256 dataVersion - ) internal { - bytes31 paramsHash = _buildParamsHash(payment, callbackAddress, callbackFunctionId, expiration); - require(s_commitments[requestId].paramsHash == paramsHash, "Params do not match request ID"); - require(s_commitments[requestId].dataVersion <= _safeCastToUint8(dataVersion), "Data versions must match"); - s_tokensInEscrow = s_tokensInEscrow.sub(payment); - delete s_commitments[requestId]; - } - - /** - * @notice Build the bytes31 hash from the payment, callback and expiration. - * @param payment The payment amount that will be released for the oracle (specified in wei) - * @param callbackAddress The callback address to call for fulfillment - * @param callbackFunctionId The callback function ID to use for fulfillment - * @param expiration The expiration that the node should respond by before the requester can cancel - * @return hash bytes31 - */ - function _buildParamsHash( - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration - ) internal pure returns (bytes31) { - return bytes31(keccak256(abi.encodePacked(payment, callbackAddress, callbackFunctionId, expiration))); - } - - /** - * @notice Safely cast uint256 to uint8 - * @param number uint256 - * @return uint8 number - */ - function _safeCastToUint8(uint256 number) internal pure returns (uint8) { - require(number < MAXIMUM_DATA_VERSION, "number too big to cast"); - return uint8(number); - } - - /** - * @notice Returns the LINK available in this contract, not locked in escrow - * @return uint256 LINK tokens available - */ - function _fundsAvailable() private view returns (uint256) { - uint256 inEscrow = s_tokensInEscrow.sub(ONE_FOR_CONSISTENT_GAS_COST); - return linkToken.balanceOf(address(this)).sub(inEscrow); - } - - /** - * @notice concrete implementation of AuthorizedReceiver - * @return bool of whether sender is authorized - */ - function _canSetAuthorizedSenders() internal view override returns (bool) { - return isAuthorizedSender(msg.sender) || owner() == msg.sender; - } - - // MODIFIERS - - /** - * @dev Reverts if the first 32 bytes of the bytes array is not equal to requestId - * @param requestId bytes32 - * @param data bytes - */ - modifier validateMultiWordResponseId(bytes32 requestId, bytes calldata data) { - require(data.length >= 32, "Response must be > 32 bytes"); - bytes32 firstDataWord; - assembly { - firstDataWord := calldataload(data.offset) - } - require(requestId == firstDataWord, "First word must be requestId"); - _; - } - - /** - * @dev Reverts if amount requested is greater than withdrawable balance - * @param amount The given amount to compare to `s_withdrawableTokens` - */ - modifier validateAvailableFunds(uint256 amount) { - require(_fundsAvailable() >= amount, "Amount requested is greater than withdrawable balance"); - _; - } - - /** - * @dev Reverts if request ID does not exist - * @param requestId The given request ID to check in stored `commitments` - */ - modifier validateRequestId(bytes32 requestId) { - require(s_commitments[requestId].paramsHash != 0, "Must have a valid requestId"); - _; - } - - /** - * @dev Reverts if the callback address is the LINK token - * @param to The callback address - */ - modifier validateNotToLINK(address to) { - require(to != address(linkToken), "Cannot call to LINK"); - _; - } - - /** - * @dev Reverts if the target address is owned by the operator - */ - modifier validateCallbackAddress(address callbackAddress) { - require(!s_owned[callbackAddress], "Cannot call owned contract"); - _; - } -} diff --git a/contracts/src/v0.7/OperatorFactory.sol b/contracts/src/v0.7/OperatorFactory.sol deleted file mode 100644 index b137ab4b3bd..00000000000 --- a/contracts/src/v0.7/OperatorFactory.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./Operator.sol"; -import "./AuthorizedForwarder.sol"; - -/** - * @title Operator Factory - * @notice Creates Operator contracts for node operators - */ -contract OperatorFactory { - address public immutable getChainlinkToken; - mapping(address => bool) private s_created; - - event OperatorCreated(address indexed operator, address indexed owner, address indexed sender); - event AuthorizedForwarderCreated(address indexed forwarder, address indexed owner, address indexed sender); - - /** - * @param linkAddress address - */ - constructor(address linkAddress) { - getChainlinkToken = linkAddress; - } - - /** - * @notice The type and version of this contract - * @return Type and version string - */ - function typeAndVersion() external pure virtual returns (string memory) { - return "OperatorFactory 1.0.0"; - } - - /** - * @notice creates a new Operator contract with the msg.sender as owner - */ - function deployNewOperator() external returns (address) { - Operator operator = new Operator(getChainlinkToken, msg.sender); - - s_created[address(operator)] = true; - emit OperatorCreated(address(operator), msg.sender, msg.sender); - - return address(operator); - } - - /** - * @notice creates a new Operator contract with the msg.sender as owner and a - * new Operator Forwarder with the Operator as the owner - */ - function deployNewOperatorAndForwarder() external returns (address, address) { - Operator operator = new Operator(getChainlinkToken, msg.sender); - s_created[address(operator)] = true; - emit OperatorCreated(address(operator), msg.sender, msg.sender); - - bytes memory tmp = new bytes(0); - AuthorizedForwarder forwarder = new AuthorizedForwarder(getChainlinkToken, address(this), address(operator), tmp); - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), address(this), msg.sender); - - return (address(operator), address(forwarder)); - } - - /** - * @notice creates a new Forwarder contract with the msg.sender as owner - */ - function deployNewForwarder() external returns (address) { - bytes memory tmp = new bytes(0); - AuthorizedForwarder forwarder = new AuthorizedForwarder(getChainlinkToken, msg.sender, address(0), tmp); - - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); - - return address(forwarder); - } - - /** - * @notice creates a new Forwarder contract with the msg.sender as owner - */ - function deployNewForwarderAndTransferOwnership(address to, bytes calldata message) external returns (address) { - AuthorizedForwarder forwarder = new AuthorizedForwarder(getChainlinkToken, msg.sender, to, message); - - s_created[address(forwarder)] = true; - emit AuthorizedForwarderCreated(address(forwarder), msg.sender, msg.sender); - - return address(forwarder); - } - - /** - * @notice indicates whether this factory deployed an address - */ - function created(address query) external view returns (bool) { - return s_created[query]; - } -} diff --git a/contracts/src/v0.7/UpkeepRegistrationRequests.sol b/contracts/src/v0.7/UpkeepRegistrationRequests.sol deleted file mode 100644 index 9c0fe6efc81..00000000000 --- a/contracts/src/v0.7/UpkeepRegistrationRequests.sol +++ /dev/null @@ -1,334 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./interfaces/LinkTokenInterface.sol"; -import "./interfaces/KeeperRegistryInterface.sol"; -import "./interfaces/TypeAndVersionInterface.sol"; -import "./vendor/SafeMath96.sol"; -import "./ConfirmedOwner.sol"; - -/** - * @notice Contract to accept requests for upkeep registrations - * @dev There are 2 registration workflows in this contract - * Flow 1. auto approve OFF / manual registration - UI calls `register` function on this contract, this contract owner at a later time then manually - * calls `approve` to register upkeep and emit events to inform UI and others interested. - * Flow 2. auto approve ON / real time registration - UI calls `register` function as before, which calls the `registerUpkeep` function directly on - * keeper registry and then emits approved event to finish the flow automatically without manual intervention. - * The idea is to have same interface(functions,events) for UI or anyone using this contract irrespective of auto approve being enabled or not. - * they can just listen to `RegistrationRequested` & `RegistrationApproved` events and know the status on registrations. - */ -contract UpkeepRegistrationRequests is TypeAndVersionInterface, ConfirmedOwner { - using SafeMath96 for uint96; - - bytes4 private constant REGISTER_REQUEST_SELECTOR = this.register.selector; - - uint256 private s_minLINKJuels; - mapping(bytes32 => PendingRequest) private s_pendingRequests; - - LinkTokenInterface public immutable LINK; - - /** - * @notice versions: - * - UpkeepRegistration 1.0.0: initial release - */ - string public constant override typeAndVersion = "UpkeepRegistrationRequests 1.0.0"; - - struct AutoApprovedConfig { - bool enabled; - uint16 allowedPerWindow; - uint32 windowSizeInBlocks; - uint64 windowStart; - uint16 approvedInCurrentWindow; - } - - struct PendingRequest { - address admin; - uint96 balance; - } - - AutoApprovedConfig private s_config; - KeeperRegistryBaseInterface private s_keeperRegistry; - - event RegistrationRequested( - bytes32 indexed hash, - string name, - bytes encryptedEmail, - address indexed upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes checkData, - uint96 amount, - uint8 indexed source - ); - - event RegistrationApproved(bytes32 indexed hash, string displayName, uint256 indexed upkeepId); - - event RegistrationRejected(bytes32 indexed hash); - - event ConfigChanged( - bool enabled, - uint32 windowSizeInBlocks, - uint16 allowedPerWindow, - address keeperRegistry, - uint256 minLINKJuels - ); - - constructor(address LINKAddress, uint256 minimumLINKJuels) ConfirmedOwner(msg.sender) { - LINK = LinkTokenInterface(LINKAddress); - s_minLINKJuels = minimumLINKJuels; - } - - //EXTERNAL - - /** - * @notice register can only be called through transferAndCall on LINK contract - * @param name string of the upkeep to be registered - * @param encryptedEmail email address of upkeep contact - * @param upkeepContract address to perform upkeep on - * @param gasLimit amount of gas to provide the target contract when performing upkeep - * @param adminAddress address to cancel upkeep and withdraw remaining funds - * @param checkData data passed to the contract when checking for upkeep - * @param amount quantity of LINK upkeep is funded with (specified in Juels) - * @param source application sending this request - */ - function register( - string memory name, - bytes calldata encryptedEmail, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - uint96 amount, - uint8 source - ) external onlyLINK { - require(adminAddress != address(0), "invalid admin address"); - bytes32 hash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); - - emit RegistrationRequested( - hash, - name, - encryptedEmail, - upkeepContract, - gasLimit, - adminAddress, - checkData, - amount, - source - ); - - AutoApprovedConfig memory config = s_config; - if (config.enabled && _underApprovalLimit(config)) { - _incrementApprovedCount(config); - - _approve(name, upkeepContract, gasLimit, adminAddress, checkData, amount, hash); - } else { - uint96 newBalance = s_pendingRequests[hash].balance.add(amount); - s_pendingRequests[hash] = PendingRequest({admin: adminAddress, balance: newBalance}); - } - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - bytes32 hash - ) external onlyOwner { - PendingRequest memory request = s_pendingRequests[hash]; - require(request.admin != address(0), "request not found"); - bytes32 expectedHash = keccak256(abi.encode(upkeepContract, gasLimit, adminAddress, checkData)); - require(hash == expectedHash, "hash and payload do not match"); - delete s_pendingRequests[hash]; - _approve(name, upkeepContract, gasLimit, adminAddress, checkData, request.balance, hash); - } - - /** - * @notice cancel will remove a registration request and return the refunds to the msg.sender - * @param hash the request hash - */ - function cancel(bytes32 hash) external { - PendingRequest memory request = s_pendingRequests[hash]; - require(msg.sender == request.admin || msg.sender == owner(), "only admin / owner can cancel"); - require(request.admin != address(0), "request not found"); - delete s_pendingRequests[hash]; - require(LINK.transfer(msg.sender, request.balance), "LINK token transfer failed"); - emit RegistrationRejected(hash); - } - - /** - * @notice owner calls this function to set if registration requests should be sent directly to the Keeper Registry - * @param enabled setting for auto-approve registrations - * @param windowSizeInBlocks window size defined in number of blocks - * @param allowedPerWindow number of registrations that can be auto approved in above window - * @param keeperRegistry new keeper registry address - */ - function setRegistrationConfig( - bool enabled, - uint32 windowSizeInBlocks, - uint16 allowedPerWindow, - address keeperRegistry, - uint256 minLINKJuels - ) external onlyOwner { - s_config = AutoApprovedConfig({ - enabled: enabled, - allowedPerWindow: allowedPerWindow, - windowSizeInBlocks: windowSizeInBlocks, - windowStart: 0, - approvedInCurrentWindow: 0 - }); - s_minLINKJuels = minLINKJuels; - s_keeperRegistry = KeeperRegistryBaseInterface(keeperRegistry); - - emit ConfigChanged(enabled, windowSizeInBlocks, allowedPerWindow, keeperRegistry, minLINKJuels); - } - - /** - * @notice read the current registration configuration - */ - function getRegistrationConfig() - external - view - returns ( - bool enabled, - uint32 windowSizeInBlocks, - uint16 allowedPerWindow, - address keeperRegistry, - uint256 minLINKJuels, - uint64 windowStart, - uint16 approvedInCurrentWindow - ) - { - AutoApprovedConfig memory config = s_config; - return ( - config.enabled, - config.windowSizeInBlocks, - config.allowedPerWindow, - address(s_keeperRegistry), - s_minLINKJuels, - config.windowStart, - config.approvedInCurrentWindow - ); - } - - /** - * @notice gets the admin address and the current balance of a registration request - */ - function getPendingRequest(bytes32 hash) external view returns (address, uint96) { - PendingRequest memory request = s_pendingRequests[hash]; - return (request.admin, request.balance); - } - - /** - * @notice Called when LINK is sent to the contract via `transferAndCall` - * @param amount Amount of LINK sent (specified in Juels) - * @param data Payload of the transaction - */ - function onTokenTransfer( - address, /* sender */ - uint256 amount, - bytes calldata data - ) external onlyLINK permittedFunctionsForLINK(data) isActualAmount(amount, data) { - require(amount >= s_minLINKJuels, "Insufficient payment"); - (bool success, ) = address(this).delegatecall(data); - // calls register - require(success, "Unable to create request"); - } - - //PRIVATE - - /** - * @dev reset auto approve window if passed end of current window - */ - function _resetWindowIfRequired(AutoApprovedConfig memory config) private { - uint64 blocksPassed = uint64(block.number - config.windowStart); - if (blocksPassed >= config.windowSizeInBlocks) { - config.windowStart = uint64(block.number); - config.approvedInCurrentWindow = 0; - s_config = config; - } - } - - /** - * @dev register upkeep on KeeperRegistry contract and emit RegistrationApproved event - */ - function _approve( - string memory name, - address upkeepContract, - uint32 gasLimit, - address adminAddress, - bytes calldata checkData, - uint96 amount, - bytes32 hash - ) private { - KeeperRegistryBaseInterface keeperRegistry = s_keeperRegistry; - - // register upkeep - uint256 upkeepId = keeperRegistry.registerUpkeep(upkeepContract, gasLimit, adminAddress, checkData); - // fund upkeep - bool success = LINK.transferAndCall(address(keeperRegistry), amount, abi.encode(upkeepId)); - require(success, "failed to fund upkeep"); - - emit RegistrationApproved(hash, name, upkeepId); - } - - /** - * @dev determine approval limits and check if in range - */ - function _underApprovalLimit(AutoApprovedConfig memory config) private returns (bool) { - _resetWindowIfRequired(config); - if (config.approvedInCurrentWindow < config.allowedPerWindow) { - return true; - } - return false; - } - - /** - * @dev record new latest approved count - */ - function _incrementApprovedCount(AutoApprovedConfig memory config) private { - config.approvedInCurrentWindow++; - s_config = config; - } - - //MODIFIERS - - /** - * @dev Reverts if not sent from the LINK token - */ - modifier onlyLINK() { - require(msg.sender == address(LINK), "Must use LINK token"); - _; - } - - /** - * @dev Reverts if the given data does not begin with the `register` function selector - * @param _data The data payload of the request - */ - modifier permittedFunctionsForLINK(bytes memory _data) { - bytes4 funcSelector; - assembly { - // solhint-disable-next-line avoid-low-level-calls - funcSelector := mload(add(_data, 32)) - } - require(funcSelector == REGISTER_REQUEST_SELECTOR, "Must use whitelisted functions"); - _; - } - - /** - * @dev Reverts if the actual amount passed does not match the expected amount - * @param expected amount that should match the actual amount - * @param data bytes - */ - modifier isActualAmount(uint256 expected, bytes memory data) { - uint256 actual; - assembly { - actual := mload(add(data, 228)) - } - require(expected == actual, "Amount mismatch"); - _; - } -} diff --git a/contracts/src/v0.7/VRFConsumerBase.sol b/contracts/src/v0.7/VRFConsumerBase.sol deleted file mode 100644 index 9956c2a0b09..00000000000 --- a/contracts/src/v0.7/VRFConsumerBase.sol +++ /dev/null @@ -1,199 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./vendor/SafeMathChainlink.sol"; - -import "./interfaces/LinkTokenInterface.sol"; - -import "./VRFRequestIDBase.sol"; - -/** **************************************************************************** - * @notice Interface for contracts using VRF randomness - * ***************************************************************************** - * @dev PURPOSE - * - * @dev Reggie the Random Oracle (not his real job) wants to provide randomness - * @dev to Vera the verifier in such a way that Vera can be sure he's not - * @dev making his output up to suit himself. Reggie provides Vera a public key - * @dev to which he knows the secret key. Each time Vera provides a seed to - * @dev Reggie, he gives back a value which is computed completely - * @dev deterministically from the seed and the secret key. - * - * @dev Reggie provides a proof by which Vera can verify that the output was - * @dev correctly computed once Reggie tells it to her, but without that proof, - * @dev the output is indistinguishable to her from a uniform random sample - * @dev from the output space. - * - * @dev The purpose of this contract is to make it easy for unrelated contracts - * @dev to talk to Vera the verifier about the work Reggie is doing, to provide - * @dev simple access to a verifiable source of randomness. - * ***************************************************************************** - * @dev USAGE - * - * @dev Calling contracts must inherit from VRFConsumerBase, and can - * @dev initialize VRFConsumerBase's attributes in their constructor as - * @dev shown: - * - * @dev contract VRFConsumer { - * @dev constructor(, address _vrfCoordinator, address _link) - * @dev VRFConsumerBase(_vrfCoordinator, _link) public { - * @dev - * @dev } - * @dev } - * - * @dev The oracle will have given you an ID for the VRF keypair they have - * @dev committed to (let's call it keyHash), and have told you the minimum LINK - * @dev price for VRF service. Make sure your contract has sufficient LINK, and - * @dev call requestRandomness(keyHash, fee, seed), where seed is the input you - * @dev want to generate randomness from. - * - * @dev Once the VRFCoordinator has received and validated the oracle's response - * @dev to your request, it will call your contract's fulfillRandomness method. - * - * @dev The randomness argument to fulfillRandomness is the actual random value - * @dev generated from your seed. - * - * @dev The requestId argument is generated from the keyHash and the seed by - * @dev makeRequestId(keyHash, seed). If your contract could have concurrent - * @dev requests open, you can use the requestId to track which seed is - * @dev associated with which randomness. See VRFRequestIDBase.sol for more - * @dev details. (See "SECURITY CONSIDERATIONS" for principles to keep in mind, - * @dev if your contract could have multiple requests in flight simultaneously.) - * - * @dev Colliding `requestId`s are cryptographically impossible as long as seeds - * @dev differ. (Which is critical to making unpredictable randomness! See the - * @dev next section.) - * - * ***************************************************************************** - * @dev SECURITY CONSIDERATIONS - * - * @dev A method with the ability to call your fulfillRandomness method directly - * @dev could spoof a VRF response with any random value, so it's critical that - * @dev it cannot be directly called by anything other than this base contract - * @dev (specifically, by the VRFConsumerBase.rawFulfillRandomness method). - * - * @dev For your users to trust that your contract's random behavior is free - * @dev from malicious interference, it's best if you can write it so that all - * @dev behaviors implied by a VRF response are executed *during* your - * @dev fulfillRandomness method. If your contract must store the response (or - * @dev anything derived from it) and use it later, you must ensure that any - * @dev user-significant behavior which depends on that stored value cannot be - * @dev manipulated by a subsequent VRF request. - * - * @dev Similarly, both miners and the VRF oracle itself have some influence - * @dev over the order in which VRF responses appear on the blockchain, so if - * @dev your contract could have multiple VRF requests in flight simultaneously, - * @dev you must ensure that the order in which the VRF responses arrive cannot - * @dev be used to manipulate your contract's user-significant behavior. - * - * @dev Since the ultimate input to the VRF is mixed with the block hash of the - * @dev block in which the request is made, user-provided seeds have no impact - * @dev on its economic security properties. They are only included for API - * @dev compatability with previous versions of this contract. - * - * @dev Since the block hash of the block which contains the requestRandomness - * @dev call is mixed into the input to the VRF *last*, a sufficiently powerful - * @dev miner could, in principle, fork the blockchain to evict the block - * @dev containing the request, forcing the request to be included in a - * @dev different block with a different hash, and therefore a different input - * @dev to the VRF. However, such an attack would incur a substantial economic - * @dev cost. This cost scales with the number of blocks the VRF oracle waits - * @dev until it calls responds to a request. - */ -abstract contract VRFConsumerBase is VRFRequestIDBase { - using SafeMathChainlink for uint256; - - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBase expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomness the VRF output - */ - function fulfillRandomness(bytes32 requestId, uint256 randomness) internal virtual; - - /** - * @dev In order to keep backwards compatibility we have kept the user - * seed field around. We remove the use of it because given that the blockhash - * enters later, it overrides whatever randomness the used seed provides. - * Given that it adds no security, and can easily lead to misunderstandings, - * we have removed it from usage and can now provide a simpler API. - */ - uint256 private constant USER_SEED_PLACEHOLDER = 0; - - /** - * @notice requestRandomness initiates a request for VRF output given _seed - * - * @dev The fulfillRandomness method receives the output, once it's provided - * @dev by the Oracle, and verified by the vrfCoordinator. - * - * @dev The _keyHash must already be registered with the VRFCoordinator, and - * @dev the _fee must exceed the fee specified during registration of the - * @dev _keyHash. - * - * @dev The _seed parameter is vestigial, and is kept only for API - * @dev compatibility with older versions. It can't *hurt* to mix in some of - * @dev your own randomness, here, but it's not necessary because the VRF - * @dev oracle will mix the hash of the block containing your request into the - * @dev VRF seed it ultimately uses. - * - * @param _keyHash ID of public key against which randomness is generated - * @param _fee The amount of LINK to send with the request - * - * @return requestId unique ID for this request - * - * @dev The returned requestId can be used to distinguish responses to - * @dev concurrent requests. It is passed as the first argument to - * @dev fulfillRandomness. - */ - function requestRandomness(bytes32 _keyHash, uint256 _fee) internal returns (bytes32 requestId) { - LINK.transferAndCall(vrfCoordinator, _fee, abi.encode(_keyHash, USER_SEED_PLACEHOLDER)); - // This is the seed passed to VRFCoordinator. The oracle will mix this with - // the hash of the block containing this request to obtain the seed/input - // which is finally passed to the VRF cryptographic machinery. - uint256 vRFSeed = makeVRFInputSeed(_keyHash, USER_SEED_PLACEHOLDER, address(this), nonces[_keyHash]); - // nonces[_keyHash] must stay in sync with - // VRFCoordinator.nonces[_keyHash][this], which was incremented by the above - // successful LINK.transferAndCall (in VRFCoordinator.randomnessRequest). - // This provides protection against the user repeating their input seed, - // which would result in a predictable/duplicate output, if multiple such - // requests appeared in the same block. - nonces[_keyHash] = nonces[_keyHash].add(1); - return makeRequestId(_keyHash, vRFSeed); - } - - LinkTokenInterface internal immutable LINK; - address private immutable vrfCoordinator; - - // Nonces for each VRF key from which randomness has been requested. - // - // Must stay in sync with VRFCoordinator[_keyHash][this] - mapping(bytes32 => uint256) /* keyHash */ /* nonce */ - private nonces; - - /** - * @param _vrfCoordinator address of VRFCoordinator contract - * @param _link address of LINK token contract - * - * @dev https://docs.chain.link/docs/link-token-contracts - */ - constructor(address _vrfCoordinator, address _link) { - vrfCoordinator = _vrfCoordinator; - LINK = LinkTokenInterface(_link); - } - - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomness(bytes32 requestId, uint256 randomness) external { - require(msg.sender == vrfCoordinator, "Only VRFCoordinator can fulfill"); - fulfillRandomness(requestId, randomness); - } -} diff --git a/contracts/src/v0.7/VRFRequestIDBase.sol b/contracts/src/v0.7/VRFRequestIDBase.sol deleted file mode 100644 index 87bb6fe20ef..00000000000 --- a/contracts/src/v0.7/VRFRequestIDBase.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -contract VRFRequestIDBase { - /** - * @notice returns the seed which is actually input to the VRF coordinator - * - * @dev To prevent repetition of VRF output due to repetition of the - * @dev user-supplied seed, that seed is combined in a hash with the - * @dev user-specific nonce, and the address of the consuming contract. The - * @dev risk of repetition is mostly mitigated by inclusion of a blockhash in - * @dev the final seed, but the nonce does protect against repetition in - * @dev requests which are included in a single block. - * - * @param _userSeed VRF seed input provided by user - * @param _requester Address of the requesting contract - * @param _nonce User-specific nonce at the time of the request - */ - function makeVRFInputSeed( - bytes32 _keyHash, - uint256 _userSeed, - address _requester, - uint256 _nonce - ) internal pure returns (uint256) { - return uint256(keccak256(abi.encode(_keyHash, _userSeed, _requester, _nonce))); - } - - /** - * @notice Returns the id for this request - * @param _keyHash The serviceAgreement ID to be used for this request - * @param _vRFInputSeed The seed to be passed directly to the VRF - * @return The id for this request - * - * @dev Note that _vRFInputSeed is not the seed passed by the consuming - * @dev contract, but the one generated by makeVRFInputSeed - */ - function makeRequestId(bytes32 _keyHash, uint256 _vRFInputSeed) internal pure returns (bytes32) { - return keccak256(abi.encodePacked(_keyHash, _vRFInputSeed)); - } -} diff --git a/contracts/src/v0.7/dev/AggregatorProxy.sol b/contracts/src/v0.7/dev/AggregatorProxy.sol deleted file mode 100644 index 9f68faa19b3..00000000000 --- a/contracts/src/v0.7/dev/AggregatorProxy.sol +++ /dev/null @@ -1,386 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../ConfirmedOwner.sol"; -import "../interfaces/AggregatorProxyInterface.sol"; - -/** - * @title A trusted proxy for updating where current answers are read from - * @notice This contract provides a consistent address for the - * CurrentAnswerInterface but delegates where it reads from to the owner, who is - * trusted to update it. - */ -contract AggregatorProxy is AggregatorProxyInterface, ConfirmedOwner { - struct Phase { - uint16 id; - AggregatorProxyInterface aggregator; - } - AggregatorProxyInterface private s_proposedAggregator; - mapping(uint16 => AggregatorProxyInterface) private s_phaseAggregators; - Phase private s_currentPhase; - - uint256 private constant PHASE_OFFSET = 64; - uint256 private constant PHASE_SIZE = 16; - uint256 private constant MAX_ID = 2**(PHASE_OFFSET + PHASE_SIZE) - 1; - - event AggregatorProposed(address indexed current, address indexed proposed); - event AggregatorConfirmed(address indexed previous, address indexed latest); - - constructor(address aggregatorAddress) ConfirmedOwner(msg.sender) { - setAggregator(aggregatorAddress); - } - - /** - * @notice Reads the current answer from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestAnswer() public view virtual override returns (int256 answer) { - return s_currentPhase.aggregator.latestAnswer(); - } - - /** - * @notice Reads the last updated height from aggregator delegated to. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestTimestamp() public view virtual override returns (uint256 updatedAt) { - return s_currentPhase.aggregator.latestTimestamp(); - } - - /** - * @notice get past rounds answers - * @param roundId the answer number to retrieve the answer for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getAnswer(uint256 roundId) public view virtual override returns (int256 answer) { - if (roundId > MAX_ID) return 0; - - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(roundId); - AggregatorProxyInterface aggregator = s_phaseAggregators[phaseId]; - if (address(aggregator) == address(0)) return 0; - - return aggregator.getAnswer(aggregatorRoundId); - } - - /** - * @notice get block timestamp when an answer was last updated - * @param roundId the answer number to retrieve the updated timestamp for - * - * @dev #[deprecated] Use getRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended getRoundData - * instead which includes better verification information. - */ - function getTimestamp(uint256 roundId) public view virtual override returns (uint256 updatedAt) { - if (roundId > MAX_ID) return 0; - - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(roundId); - AggregatorProxyInterface aggregator = s_phaseAggregators[phaseId]; - if (address(aggregator) == address(0)) return 0; - - return aggregator.getTimestamp(aggregatorRoundId); - } - - /** - * @notice get the latest completed round where the answer was updated. This - * ID includes the proxy's phase, to make sure round IDs increase even when - * switching to a newly deployed aggregator. - * - * @dev #[deprecated] Use latestRoundData instead. This does not error if no - * answer has been reached, it will simply return 0. Either wait to point to - * an already answered Aggregator or use the recommended latestRoundData - * instead which includes better verification information. - */ - function latestRound() public view virtual override returns (uint256 roundId) { - Phase memory phase = s_currentPhase; // cache storage reads - return addPhase(phase.id, uint64(phase.aggregator.latestRound())); - } - - /** - * @notice get data about a round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @param roundId the requested round ID as presented through the proxy, this - * is made up of the aggregator's round ID with the phase ID encoded in the - * two highest order bytes - * @return id is the round ID from the aggregator for which the data was - * retrieved combined with an phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function getRoundData(uint80 roundId) - public - view - virtual - override - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(roundId); - - (id, answer, startedAt, updatedAt, answeredInRound) = s_phaseAggregators[phaseId].getRoundData(aggregatorRoundId); - - return addPhaseIds(id, answer, startedAt, updatedAt, answeredInRound, phaseId); - } - - /** - * @notice get data about the latest round. Consumers are encouraged to check - * that they're receiving fresh data by inspecting the updatedAt and - * answeredInRound return values. - * Note that different underlying implementations of AggregatorV3Interface - * have slightly different semantics for some of the return values. Consumers - * should determine what implementations they expect to receive - * data from and validate that they can properly handle return data from all - * of them. - * @return id is the round ID from the aggregator for which the data was - * retrieved combined with an phase to ensure that round IDs get larger as - * time moves forward. - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @dev Note that answer and updatedAt may change between queries. - */ - function latestRoundData() - public - view - virtual - override - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - Phase memory current = s_currentPhase; // cache storage reads - - (id, answer, startedAt, updatedAt, answeredInRound) = current.aggregator.latestRoundData(); - - return addPhaseIds(id, answer, startedAt, updatedAt, answeredInRound, current.id); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @param roundId the round ID to retrieve the round data for - * @return id is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedGetRoundData(uint80 roundId) - external - view - virtual - override - hasProposal - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return s_proposedAggregator.getRoundData(roundId); - } - - /** - * @notice Used if an aggregator contract has been proposed. - * @return id is the round ID for which data was retrieved - * @return answer is the answer for the given round - * @return startedAt is the timestamp when the round was started. - * (Only some AggregatorV3Interface implementations return meaningful values) - * @return updatedAt is the timestamp when the round last was updated (i.e. - * answer was last computed) - * @return answeredInRound is the round ID of the round in which the answer - * was computed. - */ - function proposedLatestRoundData() - external - view - virtual - override - hasProposal - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return s_proposedAggregator.latestRoundData(); - } - - /** - * @notice returns the current phase's aggregator address. - */ - function aggregator() external view override returns (address) { - return address(s_currentPhase.aggregator); - } - - /** - * @notice returns the current phase's ID. - */ - function phaseId() external view override returns (uint16) { - return s_currentPhase.id; - } - - /** - * @notice represents the number of decimals the aggregator responses represent. - */ - function decimals() external view override returns (uint8) { - return s_currentPhase.aggregator.decimals(); - } - - /** - * @notice the version number representing the type of aggregator the proxy - * points to. - */ - function version() external view override returns (uint256) { - return s_currentPhase.aggregator.version(); - } - - /** - * @notice returns the description of the aggregator the proxy points to. - */ - function description() external view override returns (string memory) { - return s_currentPhase.aggregator.description(); - } - - /** - * @notice returns the current proposed aggregator - */ - function proposedAggregator() external view override returns (address) { - return address(s_proposedAggregator); - } - - /** - * @notice return a phase aggregator using the phaseId - * - * @param phaseId uint16 - */ - function phaseAggregators(uint16 phaseId) external view override returns (address) { - return address(s_phaseAggregators[phaseId]); - } - - /** - * @notice Allows the owner to propose a new address for the aggregator - * @param aggregatorAddress The new address for the aggregator contract - */ - function proposeAggregator(address aggregatorAddress) external onlyOwner { - s_proposedAggregator = AggregatorProxyInterface(aggregatorAddress); - emit AggregatorProposed(address(s_currentPhase.aggregator), aggregatorAddress); - } - - /** - * @notice Allows the owner to confirm and change the address - * to the proposed aggregator - * @dev Reverts if the given address doesn't match what was previously - * proposed - * @param aggregatorAddress The new address for the aggregator contract - */ - function confirmAggregator(address aggregatorAddress) external onlyOwner { - require(aggregatorAddress == address(s_proposedAggregator), "Invalid proposed aggregator"); - address previousAggregator = address(s_currentPhase.aggregator); - delete s_proposedAggregator; - setAggregator(aggregatorAddress); - emit AggregatorConfirmed(previousAggregator, aggregatorAddress); - } - - /* - * Internal - */ - - function setAggregator(address aggregatorAddress) internal { - uint16 id = s_currentPhase.id + 1; - s_currentPhase = Phase(id, AggregatorProxyInterface(aggregatorAddress)); - s_phaseAggregators[id] = AggregatorProxyInterface(aggregatorAddress); - } - - function addPhase(uint16 phase, uint64 originalId) internal pure returns (uint80) { - return uint80((uint256(phase) << PHASE_OFFSET) | originalId); - } - - function parseIds(uint256 roundId) internal pure returns (uint16, uint64) { - uint16 phaseId = uint16(roundId >> PHASE_OFFSET); - uint64 aggregatorRoundId = uint64(roundId); - - return (phaseId, aggregatorRoundId); - } - - function addPhaseIds( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound, - uint16 phaseId - ) - internal - pure - returns ( - uint80, - int256, - uint256, - uint256, - uint80 - ) - { - return ( - addPhase(phaseId, uint64(roundId)), - answer, - startedAt, - updatedAt, - addPhase(phaseId, uint64(answeredInRound)) - ); - } - - /* - * Modifiers - */ - - modifier hasProposal() { - require(address(s_proposedAggregator) != address(0), "No proposed aggregator present"); - _; - } -} diff --git a/contracts/src/v0.7/dev/CompoundPriceFlaggingValidator.sol b/contracts/src/v0.7/dev/CompoundPriceFlaggingValidator.sol deleted file mode 100644 index 37a15fc9cd6..00000000000 --- a/contracts/src/v0.7/dev/CompoundPriceFlaggingValidator.sol +++ /dev/null @@ -1,334 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../ConfirmedOwner.sol"; -import "../vendor/SafeMathChainlink.sol"; -import "../interfaces/FlagsInterface.sol"; -import "../interfaces/AggregatorV3Interface.sol"; -import "../interfaces/UniswapAnchoredView.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; - -/** - * @notice This validator compares the price of Chainlink aggregators against - * their equivalent Compound Open Oracle feeds. For each aggregator, a Compound - * feed is configured with its symbol, number of decimals, and deviation threshold. - * An aggregator address is flagged when its corresponding Compound feed price deviates - * by more than the configured threshold from the aggregator price. - */ -contract CompoundPriceFlaggingValidator is ConfirmedOwner, KeeperCompatibleInterface { - using SafeMathChainlink for uint256; - - struct CompoundFeedDetails { - // Used to call the Compound Open Oracle - string symbol; - // Used to convert price to match aggregator decimals - uint8 decimals; - // The numerator used to determine the threshold percentage - // as parts per billion. - // 1,000,000,000 = 100% - // 500,000,000 = 50% - // 100,000,000 = 10% - // 50,000,000 = 5% - // 10,000,000 = 1% - // 2,000,000 = 0.2% - // etc - uint32 deviationThresholdNumerator; - } - - uint256 private constant BILLION = 1_000_000_000; - - FlagsInterface private s_flags; - UniswapAnchoredView private s_compOpenOracle; - mapping(address => CompoundFeedDetails) private s_feedDetails; - - event CompoundOpenOracleAddressUpdated(address indexed from, address indexed to); - event FlagsAddressUpdated(address indexed from, address indexed to); - event FeedDetailsSet(address indexed aggregator, string symbol, uint8 decimals, uint32 deviationThresholdNumerator); - - /** - * @notice Create a new CompoundPriceFlaggingValidator - * @dev Use this contract to compare Chainlink aggregator prices - * against the Compound Open Oracle prices - * @param flagsAddress Address of the flag contract - * @param compoundOracleAddress Address of the Compound Open Oracle UniswapAnchoredView contract - */ - constructor(address flagsAddress, address compoundOracleAddress) ConfirmedOwner(msg.sender) { - setFlagsAddress(flagsAddress); - setCompoundOpenOracleAddress(compoundOracleAddress); - } - - /** - * @notice Set the address of the Compound Open Oracle UniswapAnchoredView contract - * @param oracleAddress Compound Open Oracle UniswapAnchoredView address - */ - function setCompoundOpenOracleAddress(address oracleAddress) public onlyOwner { - address previous = address(s_compOpenOracle); - if (previous != oracleAddress) { - s_compOpenOracle = UniswapAnchoredView(oracleAddress); - emit CompoundOpenOracleAddressUpdated(previous, oracleAddress); - } - } - - /** - * @notice Updates the flagging contract address for raising flags - * @param flagsAddress sets the address of the flags contract - */ - function setFlagsAddress(address flagsAddress) public onlyOwner { - address previous = address(s_flags); - if (previous != flagsAddress) { - s_flags = FlagsInterface(flagsAddress); - emit FlagsAddressUpdated(previous, flagsAddress); - } - } - - /** - * @notice Set the threshold details for comparing a Chainlink aggregator - * to a Compound Open Oracle feed. - * @param aggregator The Chainlink aggregator address - * @param compoundSymbol The symbol used by Compound for this feed - * @param compoundDecimals The number of decimals in the Compound feed - * @param compoundDeviationThresholdNumerator The threshold numerator use to determine - * the percentage with which the difference in prices must reside within. Parts per billion. - * For example: - * If prices are valid within a 5% threshold, assuming x is the compoundDeviationThresholdNumerator: - * x / 1,000,000,000 = 0.05 - * x = 50,000,000 - */ - function setFeedDetails( - address aggregator, - string calldata compoundSymbol, - uint8 compoundDecimals, - uint32 compoundDeviationThresholdNumerator - ) public onlyOwner { - require( - compoundDeviationThresholdNumerator > 0 && compoundDeviationThresholdNumerator <= BILLION, - "Invalid threshold numerator" - ); - require(_compoundPriceOf(compoundSymbol) != 0, "Invalid Compound price"); - string memory currentSymbol = s_feedDetails[aggregator].symbol; - // If symbol is not set, use the new one - if (bytes(currentSymbol).length == 0) { - s_feedDetails[aggregator] = CompoundFeedDetails({ - symbol: compoundSymbol, - decimals: compoundDecimals, - deviationThresholdNumerator: compoundDeviationThresholdNumerator - }); - emit FeedDetailsSet(aggregator, compoundSymbol, compoundDecimals, compoundDeviationThresholdNumerator); - } - // If the symbol is already set, don't change it - else { - s_feedDetails[aggregator] = CompoundFeedDetails({ - symbol: currentSymbol, - decimals: compoundDecimals, - deviationThresholdNumerator: compoundDeviationThresholdNumerator - }); - emit FeedDetailsSet(aggregator, currentSymbol, compoundDecimals, compoundDeviationThresholdNumerator); - } - } - - /** - * @notice Check the price deviation of an array of aggregators - * @dev If any of the aggregators provided have an equivalent Compound Oracle feed - * that with a price outside of the configured deviation, this function will return them. - * @param aggregators address[] memory - * @return address[] invalid feeds - */ - function check(address[] memory aggregators) public view returns (address[] memory) { - address[] memory invalidAggregators = new address[](aggregators.length); - uint256 invalidCount = 0; - for (uint256 i = 0; i < aggregators.length; i++) { - address aggregator = aggregators[i]; - if (_isInvalid(aggregator)) { - invalidAggregators[invalidCount] = aggregator; - invalidCount++; - } - } - - if (aggregators.length != invalidCount) { - assembly { - mstore(invalidAggregators, invalidCount) - } - } - return invalidAggregators; - } - - /** - * @notice Check and raise flags for any aggregator that has an equivalent Compound - * Open Oracle feed with a price deviation exceeding the configured setting. - * @dev This contract must have write permissions on the Flags contract - * @param aggregators address[] memory - * @return address[] memory invalid aggregators - */ - function update(address[] memory aggregators) public returns (address[] memory) { - address[] memory invalidAggregators = check(aggregators); - s_flags.raiseFlags(invalidAggregators); - return invalidAggregators; - } - - /** - * @notice Check the price deviation of an array of aggregators - * @dev If any of the aggregators provided have an equivalent Compound Oracle feed - * that with a price outside of the configured deviation, this function will return them. - * @param data bytes encoded address array - * @return needsUpkeep bool indicating whether upkeep needs to be performed - * @return invalid aggregators - bytes encoded address array of invalid aggregator addresses - */ - function checkUpkeep(bytes calldata data) external view override returns (bool, bytes memory) { - address[] memory invalidAggregators = check(abi.decode(data, (address[]))); - bool needsUpkeep = (invalidAggregators.length > 0); - return (needsUpkeep, abi.encode(invalidAggregators)); - } - - /** - * @notice Check and raise flags for any aggregator that has an equivalent Compound - * Open Oracle feed with a price deviation exceeding the configured setting. - * @dev This contract must have write permissions on the Flags contract - * @param data bytes encoded address array - */ - function performUpkeep(bytes calldata data) external override { - update(abi.decode(data, (address[]))); - } - - /** - * @notice Get the threshold of an aggregator - * @param aggregator address - * @return string Compound Oracle Symbol - * @return uint8 Compound Oracle Decimals - * @return uint32 Deviation Threshold Numerator - */ - function getFeedDetails(address aggregator) - public - view - returns ( - string memory, - uint8, - uint32 - ) - { - CompoundFeedDetails memory compDetails = s_feedDetails[aggregator]; - return (compDetails.symbol, compDetails.decimals, compDetails.deviationThresholdNumerator); - } - - /** - * @notice Get the flags address - * @return address - */ - function flags() external view returns (address) { - return address(s_flags); - } - - /** - * @notice Get the Compound Open Oracle address - * @return address - */ - function compoundOpenOracle() external view returns (address) { - return address(s_compOpenOracle); - } - - /** - * @notice Return the Compound oracle price of an asset using its symbol - * @param symbol string - * @return price uint256 - */ - function _compoundPriceOf(string memory symbol) private view returns (uint256) { - return s_compOpenOracle.price(symbol); - } - - // VALIDATION FUNCTIONS - - /** - * @notice Check if an aggregator has an equivalent Compound Oracle feed - * that's price is deviated more than the threshold. - * @param aggregator address of the Chainlink aggregator - * @return invalid bool. True if the deviation exceeds threshold. - */ - function _isInvalid(address aggregator) private view returns (bool invalid) { - CompoundFeedDetails memory compDetails = s_feedDetails[aggregator]; - if (compDetails.deviationThresholdNumerator == 0) { - return false; - } - // Get both oracle price details - uint256 compPrice = _compoundPriceOf(compDetails.symbol); - (uint256 aggregatorPrice, uint8 aggregatorDecimals) = _aggregatorValues(aggregator); - - // Adjust the prices so the number of decimals in each align - (aggregatorPrice, compPrice) = _adjustPriceDecimals( - aggregatorPrice, - aggregatorDecimals, - compPrice, - compDetails.decimals - ); - - // Check whether the prices deviate beyond the threshold. - return _deviatesBeyondThreshold(aggregatorPrice, compPrice, compDetails.deviationThresholdNumerator); - } - - /** - * @notice Retrieve the price and the decimals from an Aggregator - * @param aggregator address - * @return price uint256 - * @return decimals uint8 - */ - function _aggregatorValues(address aggregator) private view returns (uint256 price, uint8 decimals) { - AggregatorV3Interface priceFeed = AggregatorV3Interface(aggregator); - (, int256 signedPrice, , , ) = priceFeed.latestRoundData(); - price = uint256(signedPrice); - decimals = priceFeed.decimals(); - } - - /** - * @notice Adjust the price values of the Aggregator and Compound feeds so that - * their decimal places align. This enables deviation to be calculated. - * @param aggregatorPrice uint256 - * @param aggregatorDecimals uint8 - decimal places included in the aggregator price - * @param compoundPrice uint256 - * @param compoundDecimals uint8 - decimal places included in the compound price - * @return adjustedAggregatorPrice uint256 - * @return adjustedCompoundPrice uint256 - */ - function _adjustPriceDecimals( - uint256 aggregatorPrice, - uint8 aggregatorDecimals, - uint256 compoundPrice, - uint8 compoundDecimals - ) private pure returns (uint256 adjustedAggregatorPrice, uint256 adjustedCompoundPrice) { - if (aggregatorDecimals > compoundDecimals) { - uint8 diff = aggregatorDecimals - compoundDecimals; - uint256 multiplier = 10**uint256(diff); - compoundPrice = compoundPrice * multiplier; - } else if (aggregatorDecimals < compoundDecimals) { - uint8 diff = compoundDecimals - aggregatorDecimals; - uint256 multiplier = 10**uint256(diff); - aggregatorPrice = aggregatorPrice * multiplier; - } - adjustedAggregatorPrice = aggregatorPrice; - adjustedCompoundPrice = compoundPrice; - } - - /** - * @notice Check whether the compound price deviates from the aggregator price - * beyond the given threshold - * @dev Prices must be adjusted to match decimals prior to calling this function - * @param aggregatorPrice uint256 - * @param compPrice uint256 - * @param deviationThresholdNumerator uint32 - * @return beyondThreshold boolean. Returns true if deviation is beyond threshold. - */ - function _deviatesBeyondThreshold( - uint256 aggregatorPrice, - uint256 compPrice, - uint32 deviationThresholdNumerator - ) private pure returns (bool beyondThreshold) { - // Deviation amount threshold from the aggregator price - uint256 deviationAmountThreshold = aggregatorPrice.mul(deviationThresholdNumerator).div(BILLION); - - // Calculate deviation - uint256 deviation; - if (aggregatorPrice > compPrice) { - deviation = aggregatorPrice.sub(compPrice); - } else if (aggregatorPrice < compPrice) { - deviation = compPrice.sub(aggregatorPrice); - } - beyondThreshold = (deviation >= deviationAmountThreshold); - } -} diff --git a/contracts/src/v0.7/dev/StalenessFlaggingValidator.sol b/contracts/src/v0.7/dev/StalenessFlaggingValidator.sol deleted file mode 100644 index 070ff473e04..00000000000 --- a/contracts/src/v0.7/dev/StalenessFlaggingValidator.sol +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../ConfirmedOwner.sol"; -import "../vendor/SafeMathChainlink.sol"; -import "../interfaces/FlagsInterface.sol"; -import "../interfaces/AggregatorV3Interface.sol"; -import "../interfaces/KeeperCompatibleInterface.sol"; - -contract StalenessFlaggingValidator is ConfirmedOwner, KeeperCompatibleInterface { - using SafeMathChainlink for uint256; - - FlagsInterface private s_flags; - mapping(address => uint256) private s_thresholdSeconds; - - event FlagsAddressUpdated(address indexed previous, address indexed current); - event FlaggingThresholdUpdated(address indexed aggregator, uint256 indexed previous, uint256 indexed current); - - /** - * @notice Create a new StalenessFlaggingValidator - * @param flagsAddress Address of the flag contract - * @dev Ensure that this contract has sufficient write permissions - * on the flag contract - */ - constructor(address flagsAddress) ConfirmedOwner(msg.sender) { - setFlagsAddress(flagsAddress); - } - - /** - * @notice Updates the flagging contract address for raising flags - * @param flagsAddress sets the address of the flags contract - */ - function setFlagsAddress(address flagsAddress) public onlyOwner { - address previous = address(s_flags); - if (previous != flagsAddress) { - s_flags = FlagsInterface(flagsAddress); - emit FlagsAddressUpdated(previous, flagsAddress); - } - } - - /** - * @notice Set the threshold limits for each aggregator - * @dev parameters must be same length - * @param aggregators address[] memory - * @param flaggingThresholds uint256[] memory - */ - function setThresholds(address[] memory aggregators, uint256[] memory flaggingThresholds) public onlyOwner { - require(aggregators.length == flaggingThresholds.length, "Different sized arrays"); - for (uint256 i = 0; i < aggregators.length; i++) { - address aggregator = aggregators[i]; - uint256 previousThreshold = s_thresholdSeconds[aggregator]; - uint256 newThreshold = flaggingThresholds[i]; - if (previousThreshold != newThreshold) { - s_thresholdSeconds[aggregator] = newThreshold; - emit FlaggingThresholdUpdated(aggregator, previousThreshold, newThreshold); - } - } - } - - /** - * @notice Check for staleness in an array of aggregators - * @dev If any of the aggregators are stale, this function will return true, - * otherwise false - * @param aggregators address[] memory - * @return address[] memory stale aggregators - */ - function check(address[] memory aggregators) public view returns (address[] memory) { - uint256 currentTimestamp = block.timestamp; - address[] memory staleAggregators = new address[](aggregators.length); - uint256 staleCount = 0; - for (uint256 i = 0; i < aggregators.length; i++) { - address aggregator = aggregators[i]; - if (isStale(aggregator, currentTimestamp)) { - staleAggregators[staleCount] = aggregator; - staleCount++; - } - } - - if (aggregators.length != staleCount) { - assembly { - mstore(staleAggregators, staleCount) - } - } - return staleAggregators; - } - - /** - * @notice Check for staleness in an array of aggregators, raise a flag - * on the flags contract for each aggregator that is stale - * @dev This contract must have write permissions on the flags contract - * @param aggregators address[] memory - * @return address[] memory stale aggregators - */ - function update(address[] memory aggregators) public returns (address[] memory) { - address[] memory staleAggregators = check(aggregators); - s_flags.raiseFlags(staleAggregators); - return staleAggregators; - } - - /** - * @notice Check for staleness in an array of aggregators - * @dev Overriding KeeperInterface - * @param data bytes encoded address array - * @return needsUpkeep bool indicating whether upkeep needs to be performed - * @return staleAggregators bytes encoded address array of stale aggregator addresses - */ - function checkUpkeep(bytes calldata data) external view override returns (bool, bytes memory) { - address[] memory staleAggregators = check(abi.decode(data, (address[]))); - bool needsUpkeep = (staleAggregators.length > 0); - return (needsUpkeep, abi.encode(staleAggregators)); - } - - /** - * @notice Check for staleness in an array of aggregators, raise a flag - * on the flags contract for each aggregator that is stale - * @dev Overriding KeeperInterface - * @param data bytes encoded address array - */ - function performUpkeep(bytes calldata data) external override { - update(abi.decode(data, (address[]))); - } - - /** - * @notice Get the threshold of an aggregator - * @param aggregator address - * @return uint256 - */ - function threshold(address aggregator) external view returns (uint256) { - return s_thresholdSeconds[aggregator]; - } - - /** - * @notice Get the flags address - * @return address - */ - function flags() external view returns (address) { - return address(s_flags); - } - - /** - * @notice Check if an aggregator is stale. - * @dev Staleness is where an aggregator's `updatedAt` field is older - * than the threshold set for it in this contract - * @param aggregator address - * @param currentTimestamp uint256 - * @return stale bool - */ - function isStale(address aggregator, uint256 currentTimestamp) private view returns (bool stale) { - if (s_thresholdSeconds[aggregator] == 0) { - return false; - } - (, , , uint256 updatedAt, ) = AggregatorV3Interface(aggregator).latestRoundData(); - uint256 diff = currentTimestamp.sub(updatedAt); - if (diff > s_thresholdSeconds[aggregator]) { - return true; - } - return false; - } -} diff --git a/contracts/src/v0.7/interfaces/AggregatorInterface.sol b/contracts/src/v0.7/interfaces/AggregatorInterface.sol deleted file mode 100644 index 8eddc4a7011..00000000000 --- a/contracts/src/v0.7/interfaces/AggregatorInterface.sol +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface AggregatorInterface { - function latestAnswer() external view returns (int256); - - function latestTimestamp() external view returns (uint256); - - function latestRound() external view returns (uint256); - - function getAnswer(uint256 roundId) external view returns (int256); - - function getTimestamp(uint256 roundId) external view returns (uint256); - - event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt); - - event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt); -} diff --git a/contracts/src/v0.7/interfaces/AggregatorProxyInterface.sol b/contracts/src/v0.7/interfaces/AggregatorProxyInterface.sol deleted file mode 100644 index a56f5eb2aa5..00000000000 --- a/contracts/src/v0.7/interfaces/AggregatorProxyInterface.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./AggregatorV2V3Interface.sol"; - -interface AggregatorProxyInterface is AggregatorV2V3Interface { - function phaseAggregators(uint16 phaseId) external view returns (address); - - function phaseId() external view returns (uint16); - - function proposedAggregator() external view returns (address); - - function proposedGetRoundData(uint80 roundId) - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function proposedLatestRoundData() - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function aggregator() external view returns (address); -} diff --git a/contracts/src/v0.7/interfaces/AggregatorV2V3Interface.sol b/contracts/src/v0.7/interfaces/AggregatorV2V3Interface.sol deleted file mode 100644 index a03536879f7..00000000000 --- a/contracts/src/v0.7/interfaces/AggregatorV2V3Interface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./AggregatorInterface.sol"; -import "./AggregatorV3Interface.sol"; - -interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {} diff --git a/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol b/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol deleted file mode 100644 index 06b7b1a6eb3..00000000000 --- a/contracts/src/v0.7/interfaces/AggregatorV3Interface.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface AggregatorV3Interface { - function decimals() external view returns (uint8); - - function description() external view returns (string memory); - - function version() external view returns (uint256); - - // getRoundData and latestRoundData should both raise "No data present" - // if they do not have data to report, instead of returning unset values - // which could be misinterpreted as actual reported values. - function getRoundData(uint80 _roundId) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function latestRoundData() - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); -} diff --git a/contracts/src/v0.7/interfaces/AuthorizedReceiverInterface.sol b/contracts/src/v0.7/interfaces/AuthorizedReceiverInterface.sol deleted file mode 100644 index aec2c033328..00000000000 --- a/contracts/src/v0.7/interfaces/AuthorizedReceiverInterface.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface AuthorizedReceiverInterface { - function isAuthorizedSender(address sender) external view returns (bool); - - function getAuthorizedSenders() external returns (address[] memory); - - function setAuthorizedSenders(address[] calldata senders) external; -} diff --git a/contracts/src/v0.7/interfaces/ChainlinkRequestInterface.sol b/contracts/src/v0.7/interfaces/ChainlinkRequestInterface.sol deleted file mode 100644 index 77d2b6e0f36..00000000000 --- a/contracts/src/v0.7/interfaces/ChainlinkRequestInterface.sol +++ /dev/null @@ -1,22 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface ChainlinkRequestInterface { - function oracleRequest( - address sender, - uint256 requestPrice, - bytes32 serviceAgreementID, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function cancelOracleRequest( - bytes32 requestId, - uint256 payment, - bytes4 callbackFunctionId, - uint256 expiration - ) external; -} diff --git a/contracts/src/v0.7/interfaces/ENSInterface.sol b/contracts/src/v0.7/interfaces/ENSInterface.sol deleted file mode 100644 index 84fd654d630..00000000000 --- a/contracts/src/v0.7/interfaces/ENSInterface.sol +++ /dev/null @@ -1,34 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface ENSInterface { - // Logged when the owner of a node assigns a new owner to a subnode. - event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner); - - // Logged when the owner of a node transfers ownership to a new account. - event Transfer(bytes32 indexed node, address owner); - - // Logged when the resolver for a node changes. - event NewResolver(bytes32 indexed node, address resolver); - - // Logged when the TTL of a node changes - event NewTTL(bytes32 indexed node, uint64 ttl); - - function setSubnodeOwner( - bytes32 node, - bytes32 label, - address owner - ) external; - - function setResolver(bytes32 node, address resolver) external; - - function setOwner(bytes32 node, address owner) external; - - function setTTL(bytes32 node, uint64 ttl) external; - - function owner(bytes32 node) external view returns (address); - - function resolver(bytes32 node) external view returns (address); - - function ttl(bytes32 node) external view returns (uint64); -} diff --git a/contracts/src/v0.7/interfaces/FeedRegistryInterface.sol b/contracts/src/v0.7/interfaces/FeedRegistryInterface.sol deleted file mode 100644 index 43f5fd7b194..00000000000 --- a/contracts/src/v0.7/interfaces/FeedRegistryInterface.sol +++ /dev/null @@ -1,177 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; -pragma abicoder v2; - -import "./AggregatorV2V3Interface.sol"; - -interface FeedRegistryInterface { - struct Phase { - uint16 phaseId; - uint80 startingAggregatorRoundId; - uint80 endingAggregatorRoundId; - } - - event FeedProposed( - address indexed asset, - address indexed denomination, - address indexed proposedAggregator, - address currentAggregator, - address sender - ); - event FeedConfirmed( - address indexed asset, - address indexed denomination, - address indexed latestAggregator, - address previousAggregator, - uint16 nextPhaseId, - address sender - ); - - // V3 AggregatorV3Interface - - function decimals(address base, address quote) external view returns (uint8); - - function description(address base, address quote) external view returns (string memory); - - function version(address base, address quote) external view returns (uint256); - - function latestRoundData(address base, address quote) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function getRoundData( - address base, - address quote, - uint80 _roundId - ) - external - view - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - // V2 AggregatorInterface - - function latestAnswer(address base, address quote) external view returns (int256 answer); - - function latestTimestamp(address base, address quote) external view returns (uint256 timestamp); - - function latestRound(address base, address quote) external view returns (uint256 roundId); - - function getAnswer( - address base, - address quote, - uint256 roundId - ) external view returns (int256 answer); - - function getTimestamp( - address base, - address quote, - uint256 roundId - ) external view returns (uint256 timestamp); - - // Registry getters - - function getFeed(address base, address quote) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseFeed( - address base, - address quote, - uint16 phaseId - ) external view returns (AggregatorV2V3Interface aggregator); - - function isFeedEnabled(address aggregator) external view returns (bool); - - function getPhase( - address base, - address quote, - uint16 phaseId - ) external view returns (Phase memory phase); - - // Round helpers - - function getRoundFeed( - address base, - address quote, - uint80 roundId - ) external view returns (AggregatorV2V3Interface aggregator); - - function getPhaseRange( - address base, - address quote, - uint16 phaseId - ) external view returns (uint80 startingRoundId, uint80 endingRoundId); - - function getPreviousRoundId( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 previousRoundId); - - function getNextRoundId( - address base, - address quote, - uint80 roundId - ) external view returns (uint80 nextRoundId); - - // Feed management - - function proposeFeed( - address base, - address quote, - address aggregator - ) external; - - function confirmFeed( - address base, - address quote, - address aggregator - ) external; - - // Proposed aggregator - - function getProposedFeed(address base, address quote) - external - view - returns (AggregatorV2V3Interface proposedAggregator); - - function proposedGetRoundData( - address base, - address quote, - uint80 roundId - ) - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - function proposedLatestRoundData(address base, address quote) - external - view - returns ( - uint80 id, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ); - - // Phases - function getCurrentPhaseId(address base, address quote) external view returns (uint16 currentPhaseId); -} diff --git a/contracts/src/v0.7/interfaces/FlagsInterface.sol b/contracts/src/v0.7/interfaces/FlagsInterface.sol deleted file mode 100644 index 157d1ed46de..00000000000 --- a/contracts/src/v0.7/interfaces/FlagsInterface.sol +++ /dev/null @@ -1,16 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface FlagsInterface { - function getFlag(address) external view returns (bool); - - function getFlags(address[] calldata) external view returns (bool[] memory); - - function raiseFlag(address) external; - - function raiseFlags(address[] calldata) external; - - function lowerFlags(address[] calldata) external; - - function setRaisingAccessController(address) external; -} diff --git a/contracts/src/v0.7/interfaces/KeeperCompatibleInterface.sol b/contracts/src/v0.7/interfaces/KeeperCompatibleInterface.sol deleted file mode 100644 index c14de02c25c..00000000000 --- a/contracts/src/v0.7/interfaces/KeeperCompatibleInterface.sol +++ /dev/null @@ -1,42 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.7.0; - -interface KeeperCompatibleInterface { - /** - * @notice method that is simulated by the keepers to see if any work actually - * needs to be performed. This method does does not actually need to be - * executable, and since it is only ever simulated it can consume lots of gas. - * @dev To ensure that it is never called, you may want to add the - * cannotExecute modifier from KeeperBase to your implementation of this - * method. - * @param checkData specified in the upkeep registration so it is always the - * same for a registered upkeep. This can easily be broken down into specific - * arguments using `abi.decode`, so multiple upkeeps can be registered on the - * same contract and easily differentiated by the contract. - * @return upkeepNeeded boolean to indicate whether the keeper should call - * performUpkeep or not. - * @return performData bytes that the keeper should call performUpkeep with, if - * upkeep is needed. If you would like to encode data to decode later, try - * `abi.encode`. - */ - function checkUpkeep(bytes calldata checkData) external returns (bool upkeepNeeded, bytes memory performData); - - /** - * @notice method that is actually executed by the keepers, via the registry. - * The data returned by the checkUpkeep simulation will be passed into - * this method to actually be executed. - * @dev The input to this method should not be trusted, and the caller of the - * method should not even be restricted to any single registry. Anyone should - * be able call it, and the input should be validated, there is no guarantee - * that the data passed in is the performData returned from checkUpkeep. This - * could happen due to malicious keepers, racing keepers, or simply a state - * change while the performUpkeep transaction is waiting for confirmation. - * Always validate the data passed in. - * @param performData is the data which was passed back from the checkData - * simulation. If it is encoded, it can easily be decoded into other types by - * calling `abi.decode`. This data should not be trusted, and should be - * validated against the contract's current state. - */ - function performUpkeep(bytes calldata performData) external; -} diff --git a/contracts/src/v0.7/interfaces/KeeperRegistryInterface.sol b/contracts/src/v0.7/interfaces/KeeperRegistryInterface.sol deleted file mode 100644 index df5ea92860a..00000000000 --- a/contracts/src/v0.7/interfaces/KeeperRegistryInterface.sol +++ /dev/null @@ -1,89 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.7.0; - -interface KeeperRegistryBaseInterface { - function registerUpkeep( - address target, - uint32 gasLimit, - address admin, - bytes calldata checkData - ) external returns (uint256 id); - - function performUpkeep(uint256 id, bytes calldata performData) external returns (bool success); - - function cancelUpkeep(uint256 id) external; - - function addFunds(uint256 id, uint96 amount) external; - - function getUpkeep(uint256 id) - external - view - returns ( - address target, - uint32 executeGas, - bytes memory checkData, - uint96 balance, - address lastKeeper, - address admin, - uint64 maxValidBlocknumber - ); - - function getUpkeepCount() external view returns (uint256); - - function getCanceledUpkeepList() external view returns (uint256[] memory); - - function getKeeperList() external view returns (address[] memory); - - function getKeeperInfo(address query) - external - view - returns ( - address payee, - bool active, - uint96 balance - ); - - function getConfig() - external - view - returns ( - uint32 paymentPremiumPPB, - uint24 checkFrequencyBlocks, - uint32 checkGasLimit, - uint24 stalenessSeconds, - uint16 gasCeilingMultiplier, - uint256 fallbackGasPrice, - uint256 fallbackLinkPrice - ); -} - -/** - * @dev The view methods are not actually marked as view in the implementation - * but we want them to be easily queried off-chain. Solidity will not compile - * if we actually inherit from this interface, so we document it here. - */ -interface KeeperRegistryInterface is KeeperRegistryBaseInterface { - function checkUpkeep(uint256 upkeepId, address from) - external - view - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - int256 gasWei, - int256 linkEth - ); -} - -interface KeeperRegistryExecutableInterface is KeeperRegistryBaseInterface { - function checkUpkeep(uint256 upkeepId, address from) - external - returns ( - bytes memory performData, - uint256 maxLinkPayment, - uint256 gasLimit, - uint256 adjustedGasWei, - uint256 linkEth - ); -} diff --git a/contracts/src/v0.7/interfaces/LinkTokenInterface.sol b/contracts/src/v0.7/interfaces/LinkTokenInterface.sol deleted file mode 100644 index d9b59c7a9d2..00000000000 --- a/contracts/src/v0.7/interfaces/LinkTokenInterface.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface LinkTokenInterface { - function allowance(address owner, address spender) external view returns (uint256 remaining); - - function approve(address spender, uint256 value) external returns (bool success); - - function balanceOf(address owner) external view returns (uint256 balance); - - function decimals() external view returns (uint8 decimalPlaces); - - function decreaseApproval(address spender, uint256 addedValue) external returns (bool success); - - function increaseApproval(address spender, uint256 subtractedValue) external; - - function name() external view returns (string memory tokenName); - - function symbol() external view returns (string memory tokenSymbol); - - function totalSupply() external view returns (uint256 totalTokensIssued); - - function transfer(address to, uint256 value) external returns (bool success); - - function transferAndCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success); - - function transferFrom( - address from, - address to, - uint256 value - ) external returns (bool success); -} diff --git a/contracts/src/v0.7/interfaces/OperatorInterface.sol b/contracts/src/v0.7/interfaces/OperatorInterface.sol deleted file mode 100644 index 2a76a8b2056..00000000000 --- a/contracts/src/v0.7/interfaces/OperatorInterface.sol +++ /dev/null @@ -1,32 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "./ChainlinkRequestInterface.sol"; -import "./OracleInterface.sol"; - -interface OperatorInterface is ChainlinkRequestInterface, OracleInterface { - function operatorRequest( - address sender, - uint256 payment, - bytes32 specId, - bytes4 callbackFunctionId, - uint256 nonce, - uint256 dataVersion, - bytes calldata data - ) external; - - function fulfillOracleRequest2( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes calldata data - ) external returns (bool); - - function ownerTransferAndCall( - address to, - uint256 value, - bytes calldata data - ) external returns (bool success); -} diff --git a/contracts/src/v0.7/interfaces/OracleInterface.sol b/contracts/src/v0.7/interfaces/OracleInterface.sol deleted file mode 100644 index bf54fc0506f..00000000000 --- a/contracts/src/v0.7/interfaces/OracleInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface OracleInterface { - function fulfillOracleRequest( - bytes32 requestId, - uint256 payment, - address callbackAddress, - bytes4 callbackFunctionId, - uint256 expiration, - bytes32 data - ) external returns (bool); - - function withdraw(address recipient, uint256 amount) external; - - function withdrawable() external view returns (uint256); -} diff --git a/contracts/src/v0.7/interfaces/OwnableInterface.sol b/contracts/src/v0.7/interfaces/OwnableInterface.sol deleted file mode 100644 index 94900657baa..00000000000 --- a/contracts/src/v0.7/interfaces/OwnableInterface.sol +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface OwnableInterface { - function owner() external returns (address); - - function transferOwnership(address recipient) external; - - function acceptOwnership() external; -} diff --git a/contracts/src/v0.7/interfaces/PointerInterface.sol b/contracts/src/v0.7/interfaces/PointerInterface.sol deleted file mode 100644 index ee3d8ae9ced..00000000000 --- a/contracts/src/v0.7/interfaces/PointerInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface PointerInterface { - function getAddress() external view returns (address); -} diff --git a/contracts/src/v0.7/interfaces/TypeAndVersionInterface.sol b/contracts/src/v0.7/interfaces/TypeAndVersionInterface.sol deleted file mode 100644 index 6adff620259..00000000000 --- a/contracts/src/v0.7/interfaces/TypeAndVersionInterface.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -abstract contract TypeAndVersionInterface { - function typeAndVersion() external pure virtual returns (string memory); -} diff --git a/contracts/src/v0.7/interfaces/UniswapAnchoredView.sol b/contracts/src/v0.7/interfaces/UniswapAnchoredView.sol deleted file mode 100644 index f750cc29084..00000000000 --- a/contracts/src/v0.7/interfaces/UniswapAnchoredView.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -// Compound Finance's oracle interface -interface UniswapAnchoredView { - function price(string memory symbol) external view returns (uint256); -} diff --git a/contracts/src/v0.7/interfaces/WithdrawalInterface.sol b/contracts/src/v0.7/interfaces/WithdrawalInterface.sol deleted file mode 100644 index 8049850a796..00000000000 --- a/contracts/src/v0.7/interfaces/WithdrawalInterface.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -interface WithdrawalInterface { - /** - * @notice transfer LINK held by the contract belonging to msg.sender to - * another address - * @param recipient is the address to send the LINK to - * @param amount is the amount of LINK to send - */ - function withdraw(address recipient, uint256 amount) external; - - /** - * @notice query the available amount of LINK to withdraw by msg.sender - */ - function withdrawable() external view returns (uint256); -} diff --git a/contracts/src/v0.7/tests/ChainlinkClientTestHelper.sol b/contracts/src/v0.7/tests/ChainlinkClientTestHelper.sol deleted file mode 100644 index 5d9afb21075..00000000000 --- a/contracts/src/v0.7/tests/ChainlinkClientTestHelper.sol +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../ChainlinkClient.sol"; -import "../vendor/SafeMathChainlink.sol"; - -contract ChainlinkClientTestHelper is ChainlinkClient { - using SafeMathChainlink for uint256; - - constructor(address _link, address _oracle) { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - } - - event Request(bytes32 id, address callbackAddress, bytes4 callbackfunctionSelector, bytes data); - event LinkAmount(uint256 amount); - - function publicNewRequest( - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature - ) public { - Chainlink.Request memory req = buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - emit Request(req.id, req.callbackAddress, req.callbackFunctionId, req.buf.buf); - } - - function publicRequest( - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory req = buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - sendChainlinkRequest(req, _wei); - } - - function publicRequestRunTo( - address _oracle, - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = buildChainlinkRequest(_id, _address, bytes4(keccak256(_fulfillmentSignature))); - sendChainlinkRequestTo(_oracle, run, _wei); - } - - function publicRequestOracleData( - bytes32 _id, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory req = buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - sendOperatorRequest(req, _wei); - } - - function publicRequestOracleDataFrom( - address _oracle, - bytes32 _id, - address _address, - bytes memory _fulfillmentSignature, - uint256 _wei - ) public { - Chainlink.Request memory run = buildOperatorRequest(_id, bytes4(keccak256(_fulfillmentSignature))); - sendOperatorRequestTo(_oracle, run, _wei); - } - - function publicCancelRequest( - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - cancelChainlinkRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function publicChainlinkToken() public view returns (address) { - return chainlinkTokenAddress(); - } - - function publicFulfillChainlinkRequest(bytes32 _requestId, bytes32) public { - fulfillRequest(_requestId, bytes32(0)); - } - - function fulfillRequest(bytes32 _requestId, bytes32) public { - validateChainlinkCallback(_requestId); - } - - function publicLINK(uint256 _amount) public { - emit LinkAmount(LINK_DIVISIBILITY.mul(_amount)); - } - - function publicOracleAddress() public view returns (address) { - return chainlinkOracleAddress(); - } - - function publicAddExternalRequest(address _oracle, bytes32 _requestId) public { - addChainlinkExternalRequest(_oracle, _requestId); - } -} diff --git a/contracts/src/v0.7/tests/ChainlinkTestHelper.sol b/contracts/src/v0.7/tests/ChainlinkTestHelper.sol deleted file mode 100644 index 6a27e1e60ee..00000000000 --- a/contracts/src/v0.7/tests/ChainlinkTestHelper.sol +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../Chainlink.sol"; -import "../vendor/CBORChainlink.sol"; -import "../vendor/BufferChainlink.sol"; - -contract ChainlinkTestHelper { - using Chainlink for Chainlink.Request; - using CBORChainlink for BufferChainlink.buffer; - - Chainlink.Request private req; - - event RequestData(bytes payload); - - function closeEvent() public { - emit RequestData(req.buf.buf); - } - - function setBuffer(bytes memory data) public { - Chainlink.Request memory r2 = req; - r2.setBuffer(data); - req = r2; - } - - function add(string memory _key, string memory _value) public { - Chainlink.Request memory r2 = req; - r2.add(_key, _value); - req = r2; - } - - function addBytes(string memory _key, bytes memory _value) public { - Chainlink.Request memory r2 = req; - r2.addBytes(_key, _value); - req = r2; - } - - function addInt(string memory _key, int256 _value) public { - Chainlink.Request memory r2 = req; - r2.addInt(_key, _value); - req = r2; - } - - function addUint(string memory _key, uint256 _value) public { - Chainlink.Request memory r2 = req; - r2.addUint(_key, _value); - req = r2; - } - - // Temporarily have method receive bytes32[] memory until experimental - // string[] memory can be invoked from truffle tests. - function addStringArray(string memory _key, bytes32[] memory _values) public { - string[] memory strings = new string[](_values.length); - for (uint256 i = 0; i < _values.length; i++) { - strings[i] = bytes32ToString(_values[i]); - } - Chainlink.Request memory r2 = req; - r2.addStringArray(_key, strings); - req = r2; - } - - function bytes32ToString(bytes32 x) private pure returns (string memory) { - bytes memory bytesString = new bytes(32); - uint256 charCount = 0; - for (uint256 j = 0; j < 32; j++) { - bytes1 char = bytes1(bytes32(uint256(x) * 2**(8 * j))); - if (char != 0) { - bytesString[charCount] = char; - charCount++; - } - } - bytes memory bytesStringTrimmed = new bytes(charCount); - for (uint256 j = 0; j < charCount; j++) { - bytesStringTrimmed[j] = bytesString[j]; - } - return string(bytesStringTrimmed); - } -} diff --git a/contracts/src/v0.7/tests/Consumer.sol b/contracts/src/v0.7/tests/Consumer.sol deleted file mode 100644 index 99934df1cd2..00000000000 --- a/contracts/src/v0.7/tests/Consumer.sol +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../ChainlinkClient.sol"; - -contract Consumer is ChainlinkClient { - using Chainlink for Chainlink.Request; - - bytes32 internal specId; - bytes32 public currentPrice; - uint256 public currentPriceInt; - - event RequestFulfilled( - bytes32 indexed requestId, // User-defined ID - bytes32 indexed price - ); - - constructor( - address _link, - address _oracle, - bytes32 _specId - ) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - specId = _specId; - } - - function setSpecID(bytes32 _specId) public { - specId = _specId; - } - - function requestEthereumPrice(string memory _currency, uint256 _payment) public { - Chainlink.Request memory req = buildOperatorRequest(specId, this.fulfill.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); - string[] memory path = new string[](1); - path[0] = _currency; - req.addStringArray("path", path); - // version 2 - sendChainlinkRequest(req, _payment); - } - - function requestMultipleParametersWithCustomURLs( - string memory _urlUSD, - string memory _pathUSD, - uint256 _payment - ) public { - Chainlink.Request memory req = buildOperatorRequest(specId, this.fulfillParametersWithCustomURLs.selector); - req.add("urlUSD", _urlUSD); - req.add("pathUSD", _pathUSD); - sendChainlinkRequest(req, _payment); - } - - function cancelRequest( - address _oracle, - bytes32 _requestId, - uint256 _payment, - bytes4 _callbackFunctionId, - uint256 _expiration - ) public { - ChainlinkRequestInterface requested = ChainlinkRequestInterface(_oracle); - requested.cancelOracleRequest(_requestId, _payment, _callbackFunctionId, _expiration); - } - - function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress()); - require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); - } - - function addExternalRequest(address _oracle, bytes32 _requestId) external { - addChainlinkExternalRequest(_oracle, _requestId); - } - - function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { - emit RequestFulfilled(_requestId, _price); - currentPrice = _price; - } - - function fulfillParametersWithCustomURLs(bytes32 _requestId, uint256 _price) - public - recordChainlinkFulfillment(_requestId) - { - emit RequestFulfilled(_requestId, bytes32(_price)); - currentPriceInt = _price; - } -} diff --git a/contracts/src/v0.7/tests/KeeperCompatibleTestHelper.sol b/contracts/src/v0.7/tests/KeeperCompatibleTestHelper.sol deleted file mode 100644 index 0cf86848766..00000000000 --- a/contracts/src/v0.7/tests/KeeperCompatibleTestHelper.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../KeeperCompatible.sol"; - -contract KeeperCompatibleTestHelper is KeeperCompatible { - function checkUpkeep(bytes calldata) external override returns (bool, bytes memory) {} - - function performUpkeep(bytes calldata) external override {} - - function verifyCannotExecute() public view cannotExecute {} -} diff --git a/contracts/src/v0.7/tests/MockCompoundOracle.sol b/contracts/src/v0.7/tests/MockCompoundOracle.sol deleted file mode 100644 index 0b9ff5774ec..00000000000 --- a/contracts/src/v0.7/tests/MockCompoundOracle.sol +++ /dev/null @@ -1,28 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../interfaces/UniswapAnchoredView.sol"; - -contract MockCompoundOracle is UniswapAnchoredView { - struct OracleDetails { - uint256 price; - uint256 decimals; - } - - mapping(string => OracleDetails) s_oracleDetails; - - function price(string memory symbol) external view override returns (uint256) { - return s_oracleDetails[symbol].price; - } - - function setPrice( - string memory symbol, - uint256 newPrice, - uint256 newDecimals - ) public { - OracleDetails memory details = s_oracleDetails[symbol]; - details.price = newPrice; - details.decimals = newDecimals; - s_oracleDetails[symbol] = details; - } -} diff --git a/contracts/src/v0.7/tests/MockV2Aggregator.sol b/contracts/src/v0.7/tests/MockV2Aggregator.sol deleted file mode 100644 index 2aeb8406ac1..00000000000 --- a/contracts/src/v0.7/tests/MockV2Aggregator.sol +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../interfaces/AggregatorInterface.sol"; - -/** - * @title MockV2Aggregator - * @notice Based on the HistoricAggregator contract - * @notice Use this contract when you need to test - * other contract's ability to read data from an - * aggregator contract, but how the aggregator got - * its answer is unimportant - */ -contract MockV2Aggregator is AggregatorInterface { - int256 public override latestAnswer; - uint256 public override latestTimestamp; - uint256 public override latestRound; - - mapping(uint256 => int256) public override getAnswer; - mapping(uint256 => uint256) public override getTimestamp; - mapping(uint256 => uint256) private getStartedAt; - - constructor(int256 _initialAnswer) public { - updateAnswer(_initialAnswer); - } - - function updateAnswer(int256 _answer) public { - latestAnswer = _answer; - latestTimestamp = block.timestamp; - latestRound++; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = block.timestamp; - } - - function updateRoundData( - uint256 _roundId, - int256 _answer, - uint256 _timestamp, - uint256 _startedAt - ) public { - latestRound = _roundId; - latestAnswer = _answer; - latestTimestamp = _timestamp; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = _timestamp; - getStartedAt[latestRound] = _startedAt; - } -} diff --git a/contracts/src/v0.7/tests/MockV3Aggregator.sol b/contracts/src/v0.7/tests/MockV3Aggregator.sol deleted file mode 100644 index d14a67d915a..00000000000 --- a/contracts/src/v0.7/tests/MockV3Aggregator.sol +++ /dev/null @@ -1,93 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../interfaces/AggregatorV2V3Interface.sol"; - -/** - * @title MockV3Aggregator - * @notice Based on the FluxAggregator contract - * @notice Use this contract when you need to test - * other contract's ability to read data from an - * aggregator contract, but how the aggregator got - * its answer is unimportant - */ -contract MockV3Aggregator is AggregatorV2V3Interface { - uint256 public constant override version = 0; - - uint8 public override decimals; - int256 public override latestAnswer; - uint256 public override latestTimestamp; - uint256 public override latestRound; - - mapping(uint256 => int256) public override getAnswer; - mapping(uint256 => uint256) public override getTimestamp; - mapping(uint256 => uint256) private getStartedAt; - - constructor(uint8 _decimals, int256 _initialAnswer) { - decimals = _decimals; - updateAnswer(_initialAnswer); - } - - function updateAnswer(int256 _answer) public { - latestAnswer = _answer; - latestTimestamp = block.timestamp; - latestRound++; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = block.timestamp; - getStartedAt[latestRound] = block.timestamp; - } - - function updateRoundData( - uint80 _roundId, - int256 _answer, - uint256 _timestamp, - uint256 _startedAt - ) public { - latestRound = _roundId; - latestAnswer = _answer; - latestTimestamp = _timestamp; - getAnswer[latestRound] = _answer; - getTimestamp[latestRound] = _timestamp; - getStartedAt[latestRound] = _startedAt; - } - - function getRoundData(uint80 _roundId) - external - view - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return (_roundId, getAnswer[_roundId], getStartedAt[_roundId], getTimestamp[_roundId], _roundId); - } - - function latestRoundData() - external - view - override - returns ( - uint80 roundId, - int256 answer, - uint256 startedAt, - uint256 updatedAt, - uint80 answeredInRound - ) - { - return ( - uint80(latestRound), - getAnswer[latestRound], - getStartedAt[latestRound], - getTimestamp[latestRound], - uint80(latestRound) - ); - } - - function description() external pure override returns (string memory) { - return "v0.6/tests/MockV3Aggregator.sol"; - } -} diff --git a/contracts/src/v0.7/tests/UpkeepCounter.sol b/contracts/src/v0.7/tests/UpkeepCounter.sol deleted file mode 100644 index 3c42b58255f..00000000000 --- a/contracts/src/v0.7/tests/UpkeepCounter.sol +++ /dev/null @@ -1,57 +0,0 @@ -pragma solidity ^0.7.6; - -contract UpkeepCounter { - event PerformingUpkeep( - address indexed from, - uint256 initialBlock, - uint256 lastBlock, - uint256 previousBlock, - uint256 counter - ); - - uint256 public testRange; - uint256 public interval; - uint256 public lastBlock; - uint256 public previousPerformBlock; - uint256 public initialBlock; - uint256 public counter; - - constructor(uint256 _testRange, uint256 _interval) { - testRange = _testRange; - interval = _interval; - previousPerformBlock = 0; - lastBlock = block.number; - initialBlock = 0; - counter = 0; - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - return (eligible(), data); - } - - function performUpkeep(bytes calldata performData) external { - if (initialBlock == 0) { - initialBlock = block.number; - } - lastBlock = block.number; - counter = counter + 1; - performData; - emit PerformingUpkeep(tx.origin, initialBlock, lastBlock, previousPerformBlock, counter); - previousPerformBlock = lastBlock; - } - - function eligible() public view returns (bool) { - if (initialBlock == 0) { - return true; - } - - return (block.number - initialBlock) < testRange && (block.number - lastBlock) >= interval; - } - - function setSpread(uint256 _testRange, uint256 _interval) external { - testRange = _testRange; - interval = _interval; - initialBlock = 0; - counter = 0; - } -} diff --git a/contracts/src/v0.7/tests/UpkeepPerformCounterRestrictive.sol b/contracts/src/v0.7/tests/UpkeepPerformCounterRestrictive.sol deleted file mode 100644 index 35e28584a09..00000000000 --- a/contracts/src/v0.7/tests/UpkeepPerformCounterRestrictive.sol +++ /dev/null @@ -1,85 +0,0 @@ -pragma solidity 0.7.6; - -contract UpkeepPerformCounterRestrictive { - event PerformingUpkeep(bool eligible, address from, uint256 initialCall, uint256 nextEligible, uint256 blockNumber); - - uint256 public initialCall = 0; - uint256 public nextEligible = 0; - uint256 public testRange; - uint256 public averageEligibilityCadence; - uint256 public checkGasToBurn; - uint256 public performGasToBurn; - mapping(bytes32 => bool) public dummyMap; // used to force storage lookup - - uint256 private count = 0; - - constructor(uint256 _testRange, uint256 _averageEligibilityCadence) { - testRange = _testRange; - averageEligibilityCadence = _averageEligibilityCadence; - } - - function checkUpkeep(bytes calldata data) external view returns (bool, bytes memory) { - uint256 startGas = gasleft(); - uint256 blockNum = block.number - 1; - bool dummy; - // burn gas - while (startGas - gasleft() < checkGasToBurn) { - dummy = dummy && dummyMap[blockhash(blockNum)]; // arbitrary storage reads - blockNum--; - } - return (eligible(), abi.encode(dummy)); - } - - function performUpkeep(bytes calldata) external { - uint256 startGas = gasleft(); - bool eligible = eligible(); - uint256 blockNum = block.number; - emit PerformingUpkeep(eligible, tx.origin, initialCall, nextEligible, blockNum); - require(eligible); - if (initialCall == 0) { - initialCall = blockNum; - } - nextEligible = (blockNum + (rand() % (averageEligibilityCadence * 2))) + 1; - count++; - // burn gas - blockNum--; - while (startGas - gasleft() < performGasToBurn) { - dummyMap[blockhash(blockNum)] = false; // arbitrary storage writes - blockNum--; - } - } - - function setCheckGasToBurn(uint256 value) public { - checkGasToBurn = value; - } - - function setPerformGasToBurn(uint256 value) public { - performGasToBurn = value; - } - - function getCountPerforms() public view returns (uint256) { - return count; - } - - function eligible() internal view returns (bool) { - return initialCall == 0 || (block.number - initialCall < testRange && block.number > nextEligible); - } - - function checkEligible() public view returns (bool) { - return eligible(); - } - - function reset() external { - initialCall = 0; - count = 0; - } - - function setSpread(uint256 _newTestRange, uint256 _newAverageEligibilityCadence) external { - testRange = _newTestRange; - averageEligibilityCadence = _newAverageEligibilityCadence; - } - - function rand() private view returns (uint256) { - return uint256(keccak256(abi.encode(blockhash(block.number - 1), address(this)))); - } -} diff --git a/contracts/src/v0.7/tests/UpkeepReverter.sol b/contracts/src/v0.7/tests/UpkeepReverter.sol deleted file mode 100644 index c39cbf7db4e..00000000000 --- a/contracts/src/v0.7/tests/UpkeepReverter.sol +++ /dev/null @@ -1,21 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../KeeperCompatible.sol"; - -contract UpkeepReverter is KeeperCompatible { - function checkUpkeep(bytes calldata data) - public - view - override - cannotExecute - returns (bool callable, bytes calldata executedata) - { - require(false, "!working"); - return (true, data); - } - - function performUpkeep(bytes calldata) external pure override { - require(false, "!working"); - } -} diff --git a/contracts/src/v0.7/tests/VRFCoordinatorMock.sol b/contracts/src/v0.7/tests/VRFCoordinatorMock.sol deleted file mode 100644 index a46c9a748fc..00000000000 --- a/contracts/src/v0.7/tests/VRFCoordinatorMock.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -import "../interfaces/LinkTokenInterface.sol"; -import "../VRFConsumerBase.sol"; - -contract VRFCoordinatorMock { - LinkTokenInterface public LINK; - - event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed); - - constructor(address linkAddress) public { - LINK = LinkTokenInterface(linkAddress); - } - - function onTokenTransfer( - address sender, - uint256 fee, - bytes memory _data - ) public onlyLINK { - (bytes32 keyHash, uint256 seed) = abi.decode(_data, (bytes32, uint256)); - emit RandomnessRequest(sender, keyHash, seed); - } - - function callBackWithRandomness( - bytes32 requestId, - uint256 randomness, - address consumerContract - ) public { - VRFConsumerBase v; - bytes memory resp = abi.encodeWithSelector(v.rawFulfillRandomness.selector, requestId, randomness); - uint256 b = 206000; - require(gasleft() >= b, "not enough gas for consumer"); - (bool success, ) = consumerContract.call(resp); - } - - modifier onlyLINK() { - require(msg.sender == address(LINK), "Must use LINK token"); - _; - } -} diff --git a/contracts/src/v0.7/vendor/Address.sol b/contracts/src/v0.7/vendor/Address.sol deleted file mode 100644 index eec7c36dcd7..00000000000 --- a/contracts/src/v0.7/vendor/Address.sol +++ /dev/null @@ -1,217 +0,0 @@ -// SPDX-License-Identifier: MIT -// From https://github.com/OpenZeppelin/openzeppelin-contracts v3.4.0(fa64a1ced0b70ab89073d5d0b6e01b0778f7e7d6) - -pragma solidity >=0.6.2 <0.8.0; - -/** - * @dev Collection of functions related to the address type - */ -library Address { - /** - * @dev Returns true if `account` is a contract. - * - * [IMPORTANT] - * ==== - * It is unsafe to assume that an address for which this function returns - * false is an externally-owned account (EOA) and not a contract. - * - * Among others, `isContract` will return false for the following - * types of addresses: - * - * - an externally-owned account - * - a contract in construction - * - an address where a contract will be created - * - an address where a contract lived, but was destroyed - * ==== - */ - function isContract(address account) internal view returns (bool) { - // This method relies on extcodesize, which returns 0 for contracts in - // construction, since the code is only stored at the end of the - // constructor execution. - - uint256 size; - // solhint-disable-next-line no-inline-assembly - assembly { - size := extcodesize(account) - } - return size > 0; - } - - /** - * @dev Replacement for Solidity's `transfer`: sends `amount` wei to - * `recipient`, forwarding all available gas and reverting on errors. - * - * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost - * of certain opcodes, possibly making contracts go over the 2300 gas limit - * imposed by `transfer`, making them unable to receive funds via - * `transfer`. {sendValue} removes this limitation. - * - * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. - * - * IMPORTANT: because control is transferred to `recipient`, care must be - * taken to not create reentrancy vulnerabilities. Consider using - * {ReentrancyGuard} or the - * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. - */ - function sendValue(address payable recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Address: insufficient balance"); - - // solhint-disable-next-line avoid-low-level-calls, avoid-call-value - (bool success, ) = recipient.call{value: amount}(""); - require(success, "Address: unable to send value, recipient may have reverted"); - } - - /** - * @dev Performs a Solidity function call using a low level `call`. A - * plain`call` is an unsafe replacement for a function call: use this - * function instead. - * - * If `target` reverts with a revert reason, it is bubbled up by this - * function (like regular Solidity function calls). - * - * Returns the raw returned data. To convert to the expected return value, - * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. - * - * Requirements: - * - * - `target` must be a contract. - * - calling `target` with `data` must not revert. - * - * _Available since v3.1._ - */ - function functionCall(address target, bytes memory data) internal returns (bytes memory) { - return functionCall(target, data, "Address: low-level call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with - * `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, 0, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but also transferring `value` wei to `target`. - * - * Requirements: - * - * - the calling contract must have an ETH balance of at least `value`. - * - the called Solidity function must be `payable`. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value - ) internal returns (bytes memory) { - return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); - } - - /** - * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but - * with `errorMessage` as a fallback revert reason when `target` reverts. - * - * _Available since v3.1._ - */ - function functionCallWithValue( - address target, - bytes memory data, - uint256 value, - string memory errorMessage - ) internal returns (bytes memory) { - require(address(this).balance >= value, "Address: insufficient balance for call"); - require(isContract(target), "Address: call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.call{value: value}(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { - return functionStaticCall(target, data, "Address: low-level static call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a static call. - * - * _Available since v3.3._ - */ - function functionStaticCall( - address target, - bytes memory data, - string memory errorMessage - ) internal view returns (bytes memory) { - require(isContract(target), "Address: static call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.staticcall(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { - return functionDelegateCall(target, data, "Address: low-level delegate call failed"); - } - - /** - * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], - * but performing a delegate call. - * - * _Available since v3.4._ - */ - function functionDelegateCall( - address target, - bytes memory data, - string memory errorMessage - ) internal returns (bytes memory) { - require(isContract(target), "Address: delegate call to non-contract"); - - // solhint-disable-next-line avoid-low-level-calls - (bool success, bytes memory returndata) = target.delegatecall(data); - return _verifyCallResult(success, returndata, errorMessage); - } - - function _verifyCallResult( - bool success, - bytes memory returndata, - string memory errorMessage - ) private pure returns (bytes memory) { - if (success) { - return returndata; - } else { - // Look for revert reason and bubble it up if present - if (returndata.length > 0) { - // The easiest way to bubble the revert reason is using memory via assembly - - // solhint-disable-next-line no-inline-assembly - assembly { - let returndata_size := mload(returndata) - revert(add(32, returndata), returndata_size) - } - } else { - revert(errorMessage); - } - } - } -} diff --git a/contracts/src/v0.7/vendor/BufferChainlink.sol b/contracts/src/v0.7/vendor/BufferChainlink.sol deleted file mode 100644 index 7d2056921d9..00000000000 --- a/contracts/src/v0.7/vendor/BufferChainlink.sol +++ /dev/null @@ -1,333 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -/** - * @dev A library for working with mutable byte buffers in Solidity. - * - * Byte buffers are mutable and expandable, and provide a variety of primitives - * for writing to them. At any time you can fetch a bytes object containing the - * current contents of the buffer. The bytes object should not be stored between - * operations, as it may change due to resizing of the buffer. - */ -library BufferChainlink { - /** - * @dev Represents a mutable buffer. Buffers have a current value (buf) and - * a capacity. The capacity may be longer than the current value, in - * which case it can be extended without the need to allocate more memory. - */ - struct buffer { - bytes buf; - uint256 capacity; - } - - /** - * @dev Initializes a buffer with an initial capacity. - * @param buf The buffer to initialize. - * @param capacity The number of bytes of space to allocate the buffer. - * @return The buffer, for chaining. - */ - function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) { - if (capacity % 32 != 0) { - capacity += 32 - (capacity % 32); - } - // Allocate space for the buffer data - buf.capacity = capacity; - assembly { - let ptr := mload(0x40) - mstore(buf, ptr) - mstore(ptr, 0) - mstore(0x40, add(32, add(ptr, capacity))) - } - return buf; - } - - /** - * @dev Initializes a new buffer from an existing bytes object. - * Changes to the buffer may mutate the original value. - * @param b The bytes object to initialize the buffer with. - * @return A new buffer. - */ - function fromBytes(bytes memory b) internal pure returns (buffer memory) { - buffer memory buf; - buf.buf = b; - buf.capacity = b.length; - return buf; - } - - function resize(buffer memory buf, uint256 capacity) private pure { - bytes memory oldbuf = buf.buf; - init(buf, capacity); - append(buf, oldbuf); - } - - function max(uint256 a, uint256 b) private pure returns (uint256) { - if (a > b) { - return a; - } - return b; - } - - /** - * @dev Sets buffer length to 0. - * @param buf The buffer to truncate. - * @return The original buffer, for chaining.. - */ - function truncate(buffer memory buf) internal pure returns (buffer memory) { - assembly { - let bufptr := mload(buf) - mstore(bufptr, 0) - } - return buf; - } - - /** - * @dev Writes a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The start offset to write to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function write( - buffer memory buf, - uint256 off, - bytes memory data, - uint256 len - ) internal pure returns (buffer memory) { - require(len <= data.length); - - if (off + len > buf.capacity) { - resize(buf, max(buf.capacity, len + off) * 2); - } - - uint256 dest; - uint256 src; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Start address = buffer address + offset + sizeof(buffer length) - dest := add(add(bufptr, 32), off) - // Update buffer length if we're extending it - if gt(add(len, off), buflen) { - mstore(bufptr, add(len, off)) - } - src := add(data, 32) - } - - // Copy word-length chunks while possible - for (; len >= 32; len -= 32) { - assembly { - mstore(dest, mload(src)) - } - dest += 32; - src += 32; - } - - // Copy remaining bytes - uint256 mask = 256**(32 - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) - let destpart := and(mload(dest), mask) - mstore(dest, or(destpart, srcpart)) - } - - return buf; - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @param len The number of bytes to copy. - * @return The original buffer, for chaining. - */ - function append( - buffer memory buf, - bytes memory data, - uint256 len - ) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, len); - } - - /** - * @dev Appends a byte string to a buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, data.length); - } - - /** - * @dev Writes a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write the byte at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeUint8( - buffer memory buf, - uint256 off, - uint8 data - ) internal pure returns (buffer memory) { - if (off >= buf.capacity) { - resize(buf, buf.capacity * 2); - } - - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Length of existing buffer data - let buflen := mload(bufptr) - // Address = buffer address + sizeof(buffer length) + off - let dest := add(add(bufptr, off), 32) - mstore8(dest, data) - // Update buffer length if we extended it - if eq(off, buflen) { - mstore(bufptr, add(buflen, 1)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) { - return writeUint8(buf, buf.buf.length, data); - } - - /** - * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (left-aligned). - * @return The original buffer, for chaining. - */ - function write( - buffer memory buf, - uint256 off, - bytes32 data, - uint256 len - ) private pure returns (buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint256 mask = 256**len - 1; - // Right-align data - data = data >> (8 * (32 - len)); - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + sizeof(buffer length) + off + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the - * capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function writeBytes20( - buffer memory buf, - uint256 off, - bytes20 data - ) internal pure returns (buffer memory) { - return write(buf, off, bytes32(data), 20); - } - - /** - * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chhaining. - */ - function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, bytes32(data), 20); - } - - /** - * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer, for chaining. - */ - function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) { - return write(buf, buf.buf.length, data, 32); - } - - /** - * @dev Writes an integer to the buffer. Resizes if doing so would exceed - * the capacity of the buffer. - * @param buf The buffer to append to. - * @param off The offset to write at. - * @param data The data to append. - * @param len The number of bytes to write (right-aligned). - * @return The original buffer, for chaining. - */ - function writeInt( - buffer memory buf, - uint256 off, - uint256 data, - uint256 len - ) private pure returns (buffer memory) { - if (len + off > buf.capacity) { - resize(buf, (len + off) * 2); - } - - uint256 mask = 256**len - 1; - assembly { - // Memory address of the buffer data - let bufptr := mload(buf) - // Address = buffer address + off + sizeof(buffer length) + len - let dest := add(add(bufptr, off), len) - mstore(dest, or(and(mload(dest), not(mask)), data)) - // Update buffer length if we extended it - if gt(add(off, len), mload(bufptr)) { - mstore(bufptr, add(off, len)) - } - } - return buf; - } - - /** - * @dev Appends a byte to the end of the buffer. Resizes if doing so would - * exceed the capacity of the buffer. - * @param buf The buffer to append to. - * @param data The data to append. - * @return The original buffer. - */ - function appendInt( - buffer memory buf, - uint256 data, - uint256 len - ) internal pure returns (buffer memory) { - return writeInt(buf, buf.buf.length, data, len); - } -} diff --git a/contracts/src/v0.7/vendor/CBORChainlink.sol b/contracts/src/v0.7/vendor/CBORChainlink.sol deleted file mode 100644 index 5ee0cecd203..00000000000 --- a/contracts/src/v0.7/vendor/CBORChainlink.sol +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.4.19; - -import {BufferChainlink} from "./BufferChainlink.sol"; - -library CBORChainlink { - using BufferChainlink for BufferChainlink.buffer; - - uint8 private constant MAJOR_TYPE_INT = 0; - uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1; - uint8 private constant MAJOR_TYPE_BYTES = 2; - uint8 private constant MAJOR_TYPE_STRING = 3; - uint8 private constant MAJOR_TYPE_ARRAY = 4; - uint8 private constant MAJOR_TYPE_MAP = 5; - uint8 private constant MAJOR_TYPE_TAG = 6; - uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7; - - uint8 private constant TAG_TYPE_BIGNUM = 2; - uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3; - - function encodeFixedNumeric(BufferChainlink.buffer memory buf, uint8 major, uint64 value) private pure { - if(value <= 23) { - buf.appendUint8(uint8((major << 5) | value)); - } else if (value <= 0xFF) { - buf.appendUint8(uint8((major << 5) | 24)); - buf.appendInt(value, 1); - } else if (value <= 0xFFFF) { - buf.appendUint8(uint8((major << 5) | 25)); - buf.appendInt(value, 2); - } else if (value <= 0xFFFFFFFF) { - buf.appendUint8(uint8((major << 5) | 26)); - buf.appendInt(value, 4); - } else { - buf.appendUint8(uint8((major << 5) | 27)); - buf.appendInt(value, 8); - } - } - - function encodeIndefiniteLengthType(BufferChainlink.buffer memory buf, uint8 major) private pure { - buf.appendUint8(uint8((major << 5) | 31)); - } - - function encodeUInt(BufferChainlink.buffer memory buf, uint value) internal pure { - if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, value); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value)); - } - } - - function encodeInt(BufferChainlink.buffer memory buf, int value) internal pure { - if(value < -0x10000000000000000) { - encodeSignedBigNum(buf, value); - } else if(value > 0xFFFFFFFFFFFFFFFF) { - encodeBigNum(buf, uint(value)); - } else if(value >= 0) { - encodeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(uint256(value))); - } else { - encodeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(uint256(-1 - value))); - } - } - - function encodeBytes(BufferChainlink.buffer memory buf, bytes memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length)); - buf.append(value); - } - - function encodeBigNum(BufferChainlink.buffer memory buf, uint value) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM)); - encodeBytes(buf, abi.encode(value)); - } - - function encodeSignedBigNum(BufferChainlink.buffer memory buf, int input) internal pure { - buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM)); - encodeBytes(buf, abi.encode(uint256(-1 - input))); - } - - function encodeString(BufferChainlink.buffer memory buf, string memory value) internal pure { - encodeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length)); - buf.append(bytes(value)); - } - - function startArray(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY); - } - - function startMap(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP); - } - - function endSequence(BufferChainlink.buffer memory buf) internal pure { - encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE); - } -} diff --git a/contracts/src/v0.7/vendor/Context.sol b/contracts/src/v0.7/vendor/Context.sol deleted file mode 100644 index aa7b856e245..00000000000 --- a/contracts/src/v0.7/vendor/Context.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -// github.com/OpenZeppelin/openzeppelin-contracts@fa64a1ced0b70ab89073d5d0b6e01b0778f7e7d6 - -pragma solidity ^0.7.0; - -/* - * @dev Provides information about the current execution context, including the - * sender of the transaction and its data. While these are generally available - * via msg.sender and msg.data, they should not be accessed in such a direct - * manner, since when dealing with GSN meta-transactions the account sending and - * paying for execution may not be the actual sender (as far as an application - * is concerned). - * - * This contract is only required for intermediate, library-like contracts. - */ -abstract contract Context { - function _msgSender() internal view virtual returns (address payable) { - return msg.sender; - } - - function _msgData() internal view virtual returns (bytes memory) { - this; - // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 - return msg.data; - } -} diff --git a/contracts/src/v0.7/vendor/ENSResolver.sol b/contracts/src/v0.7/vendor/ENSResolver.sol deleted file mode 100644 index d5cbc6727bf..00000000000 --- a/contracts/src/v0.7/vendor/ENSResolver.sol +++ /dev/null @@ -1,6 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -abstract contract ENSResolver { - function addr(bytes32 node) public view virtual returns (address); -} diff --git a/contracts/src/v0.7/vendor/Pausable.sol b/contracts/src/v0.7/vendor/Pausable.sol deleted file mode 100644 index 63ccdd6ce49..00000000000 --- a/contracts/src/v0.7/vendor/Pausable.sol +++ /dev/null @@ -1,91 +0,0 @@ -// SPDX-License-Identifier: MIT -// github.com/OpenZeppelin/openzeppelin-contracts@fa64a1ced0b70ab89073d5d0b6e01b0778f7e7d6 - -pragma solidity ^0.7.0; - -import "./Context.sol"; - -/** - * @dev Contract module which allows children to implement an emergency stop - * mechanism that can be triggered by an authorized account. - * - * This module is used through inheritance. It will make available the - * modifiers `whenNotPaused` and `whenPaused`, which can be applied to - * the functions of your contract. Note that they will not be pausable by - * simply including this module, only once the modifiers are put in place. - */ -abstract contract Pausable is Context { - /** - * @dev Emitted when the pause is triggered by `account`. - */ - event Paused(address account); - - /** - * @dev Emitted when the pause is lifted by `account`. - */ - event Unpaused(address account); - - bool private _paused; - - /** - * @dev Initializes the contract in unpaused state. - */ - constructor() { - _paused = false; - } - - /** - * @dev Returns true if the contract is paused, and false otherwise. - */ - function paused() public view virtual returns (bool) { - return _paused; - } - - /** - * @dev Modifier to make a function callable only when the contract is not paused. - * - * Requirements: - * - * - The contract must not be paused. - */ - modifier whenNotPaused() { - require(!paused(), "Pausable: paused"); - _; - } - - /** - * @dev Modifier to make a function callable only when the contract is paused. - * - * Requirements: - * - * - The contract must be paused. - */ - modifier whenPaused() { - require(paused(), "Pausable: not paused"); - _; - } - - /** - * @dev Triggers stopped state. - * - * Requirements: - * - * - The contract must not be paused. - */ - function _pause() internal virtual whenNotPaused { - _paused = true; - emit Paused(_msgSender()); - } - - /** - * @dev Returns to normal state. - * - * Requirements: - * - * - The contract must be paused. - */ - function _unpause() internal virtual whenPaused { - _paused = false; - emit Unpaused(_msgSender()); - } -} diff --git a/contracts/src/v0.7/vendor/ReentrancyGuard.sol b/contracts/src/v0.7/vendor/ReentrancyGuard.sol deleted file mode 100644 index aaaee1799c4..00000000000 --- a/contracts/src/v0.7/vendor/ReentrancyGuard.sol +++ /dev/null @@ -1,63 +0,0 @@ -// SPDX-License-Identifier: MIT -// github.com/OpenZeppelin/openzeppelin-contracts@fa64a1ced0b70ab89073d5d0b6e01b0778f7e7d6 - -pragma solidity ^0.7.0; - -/** - * @dev Contract module that helps prevent reentrant calls to a function. - * - * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier - * available, which can be applied to functions to make sure there are no nested - * (reentrant) calls to them. - * - * Note that because there is a single `nonReentrant` guard, functions marked as - * `nonReentrant` may not call one another. This can be worked around by making - * those functions `private`, and then adding `external` `nonReentrant` entry - * points to them. - * - * TIP: If you would like to learn more about reentrancy and alternative ways - * to protect against it, check out our blog post - * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. - */ -abstract contract ReentrancyGuard { - // Booleans are more expensive than uint256 or any type that takes up a full - // word because each write operation emits an extra SLOAD to first read the - // slot's contents, replace the bits taken up by the boolean, and then write - // back. This is the compiler's defense against contract upgrades and - // pointer aliasing, and it cannot be disabled. - - // The values being non-zero value makes deployment a bit more expensive, - // but in exchange the refund on every call to nonReentrant will be lower in - // amount. Since refunds are capped to a percentage of the total - // transaction's gas, it is best to keep them low in cases like this one, to - // increase the likelihood of the full refund coming into effect. - uint256 private constant _NOT_ENTERED = 1; - uint256 private constant _ENTERED = 2; - - uint256 private _status; - - constructor() { - _status = _NOT_ENTERED; - } - - /** - * @dev Prevents a contract from calling itself, directly or indirectly. - * Calling a `nonReentrant` function from another `nonReentrant` - * function is not supported. It is possible to prevent this from happening - * by making the `nonReentrant` function external, and make it call a - * `private` function that does the actual work. - */ - modifier nonReentrant() { - // On the first call to nonReentrant, _notEntered will be true - require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); - - // Any calls to nonReentrant after this point will fail - _status = _ENTERED; - - _; - - // By storing the original value once again, a refund is triggered (see - // https://eips.ethereum.org/EIPS/eip-2200) - _status = _NOT_ENTERED; - } -} diff --git a/contracts/src/v0.7/vendor/SafeMath96.sol b/contracts/src/v0.7/vendor/SafeMath96.sol deleted file mode 100644 index b51849950ba..00000000000 --- a/contracts/src/v0.7/vendor/SafeMath96.sol +++ /dev/null @@ -1,112 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.7.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - * - * This library is a version of Open Zeppelin's SafeMath, modified to support - * unsigned 96 bit integers. - */ -library SafeMath96 { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint96 a, uint96 b) internal pure returns (uint96) { - uint96 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint96 a, uint96 b) internal pure returns (uint96) { - require(b <= a, "SafeMath: subtraction overflow"); - uint96 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint96 a, uint96 b) internal pure returns (uint96) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint96 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint96 a, uint96 b) internal pure returns (uint96) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint96 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint96 a, uint96 b) internal pure returns (uint96) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.7/vendor/SafeMathChainlink.sol b/contracts/src/v0.7/vendor/SafeMathChainlink.sol deleted file mode 100644 index 1a95b1a7fa5..00000000000 --- a/contracts/src/v0.7/vendor/SafeMathChainlink.sol +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; - -/** - * @dev Wrappers over Solidity's arithmetic operations with added overflow - * checks. - * - * Arithmetic operations in Solidity wrap on overflow. This can easily result - * in bugs, because programmers usually assume that an overflow raises an - * error, which is the standard behavior in high level programming languages. - * `SafeMath` restores this intuition by reverting the transaction when an - * operation overflows. - * - * Using this library instead of the unchecked operations eliminates an entire - * class of bugs, so it's recommended to use it always. - */ -library SafeMathChainlink { - /** - * @dev Returns the addition of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - Addition cannot overflow. - */ - function add(uint256 a, uint256 b) internal pure returns (uint256) { - uint256 c = a + b; - require(c >= a, "SafeMath: addition overflow"); - - return c; - } - - /** - * @dev Returns the subtraction of two unsigned integers, reverting on - * overflow (when the result is negative). - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - Subtraction cannot overflow. - */ - function sub(uint256 a, uint256 b) internal pure returns (uint256) { - require(b <= a, "SafeMath: subtraction overflow"); - uint256 c = a - b; - - return c; - } - - /** - * @dev Returns the multiplication of two unsigned integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - Multiplication cannot overflow. - */ - function mul(uint256 a, uint256 b) internal pure returns (uint256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 - if (a == 0) { - return 0; - } - - uint256 c = a * b; - require(c / a == b, "SafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two unsigned integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function div(uint256 a, uint256 b) internal pure returns (uint256) { - // Solidity only automatically asserts when dividing by 0 - require(b > 0, "SafeMath: division by zero"); - uint256 c = a / b; - // assert(a == b * c + a % b); // There is no case in which this doesn't hold - - return c; - } - - /** - * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), - * Reverts when dividing by zero. - * - * Counterpart to Solidity's `%` operator. This function uses a `revert` - * opcode (which leaves remaining gas untouched) while Solidity uses an - * invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - The divisor cannot be zero. - */ - function mod(uint256 a, uint256 b) internal pure returns (uint256) { - require(b != 0, "SafeMath: modulo by zero"); - return a % b; - } -} diff --git a/contracts/src/v0.7/vendor/SignedSafeMath.sol b/contracts/src/v0.7/vendor/SignedSafeMath.sol deleted file mode 100644 index 61658cd803c..00000000000 --- a/contracts/src/v0.7/vendor/SignedSafeMath.sol +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: MIT - -pragma solidity ^0.7.0; - -/** - * @title SignedSafeMath - * @dev Signed math operations with safety checks that revert on error. - */ -library SignedSafeMath { - int256 private constant _INT256_MIN = -2**255; - - /** - * @dev Returns the multiplication of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `*` operator. - * - * Requirements: - * - * - Multiplication cannot overflow. - */ - function mul(int256 a, int256 b) internal pure returns (int256) { - // Gas optimization: this is cheaper than requiring 'a' not being zero, but the - // benefit is lost if 'b' is also tested. - // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 - if (a == 0) { - return 0; - } - - require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow"); - - int256 c = a * b; - require(c / a == b, "SignedSafeMath: multiplication overflow"); - - return c; - } - - /** - * @dev Returns the integer division of two signed integers. Reverts on - * division by zero. The result is rounded towards zero. - * - * Counterpart to Solidity's `/` operator. Note: this function uses a - * `revert` opcode (which leaves remaining gas untouched) while Solidity - * uses an invalid opcode to revert (consuming all remaining gas). - * - * Requirements: - * - * - The divisor cannot be zero. - */ - function div(int256 a, int256 b) internal pure returns (int256) { - require(b != 0, "SignedSafeMath: division by zero"); - require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow"); - - int256 c = a / b; - - return c; - } - - /** - * @dev Returns the subtraction of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `-` operator. - * - * Requirements: - * - * - Subtraction cannot overflow. - */ - function sub(int256 a, int256 b) internal pure returns (int256) { - int256 c = a - b; - require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow"); - - return c; - } - - /** - * @dev Returns the addition of two signed integers, reverting on - * overflow. - * - * Counterpart to Solidity's `+` operator. - * - * Requirements: - * - * - Addition cannot overflow. - */ - function add(int256 a, int256 b) internal pure returns (int256) { - int256 c = a + b; - require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow"); - - return c; - } -} 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 2c3bf3e2620..d2e1805d170 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 @@ -16,14 +16,14 @@ interface IAutomationRegistryMaster2_3 { error IncorrectNumberOfSignatures(); error IncorrectNumberOfSigners(); error IndexOutOfRange(); - error InsufficientBalance(int256 available, uint256 requested); - error InvalidBillingToken(); + error InsufficientBalance(uint256 available, uint256 requested); error InvalidDataLength(); error InvalidFeed(); error InvalidPayee(); error InvalidRecipient(); error InvalidReport(); error InvalidSigner(); + error InvalidToken(); error InvalidTransmitter(); error InvalidTrigger(); error InvalidTriggerType(); @@ -78,7 +78,7 @@ interface IAutomationRegistryMaster2_3 { bytes offchainConfig ); event DedupKeyAdded(bytes32 indexed dedupKey); - event FeesWithdrawn(address indexed recipient, address indexed assetAddress, uint256 amount); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); event FundsAdded(uint256 indexed id, address indexed from, uint96 amount); event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); event InsufficientFundsUpkeepReport(uint256 indexed id, bytes trigger); @@ -218,9 +218,9 @@ interface IAutomationRegistryMaster2_3 { function setUpkeepTriggerConfig(uint256 id, bytes memory triggerConfig) external; function transferUpkeepAdmin(uint256 id, address proposed) external; function unpauseUpkeep(uint256 id) external; - function withdrawERC20Fees(address assetAddress, address to, uint256 amount) external; + function withdrawERC20Fees(address asset, address to, uint256 amount) external; function withdrawFunds(uint256 id, address to) external; - function withdrawLinkFees(address to, uint256 amount) external; + function withdrawLink(address to, uint256 amount) external; function acceptPayeeship(address transmitter) external; function disableOffchainPayments() external; @@ -404,5 +404,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":"int256","name":"available","type":"int256"},{"internalType":"uint256","name":"requested","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidBillingToken","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":"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":"recipient","type":"address"},{"indexed":true,"internalType":"address","name":"assetAddress","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":"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":"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":"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":"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":"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":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"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":"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":"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":"address","name":"assetAddress","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":"withdrawLinkFees","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":"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":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","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":"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":"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":"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":"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":"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":"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":[],"name":"linkAvailableForPayment","outputs":[{"internalType":"int256","name":"","type":"int256"}],"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":"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":"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":"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":"upkeepTranscoderVersion","outputs":[{"internalType":"enum UpkeepFormat","name":"","type":"uint8"}],"stateMutability":"pure","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/test/AutomationRegistry2_3.t.sol b/contracts/src/v0.8/automation/dev/test/AutomationRegistry2_3.t.sol index 4f0f8fa4f80..7a33b9b9746 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 @@ -1,8 +1,10 @@ // SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.19; +import {Vm} from "forge-std/Test.sol"; import {BaseTest} from "./BaseTest.t.sol"; import {AutomationRegistryBase2_3 as AutoBase} from "../v2_3/AutomationRegistryBase2_3.sol"; +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"; @@ -76,6 +78,12 @@ contract SetUp is BaseTest { "", "" ); + + vm.startPrank(OWNER); + registry.addFunds(linkUpkeepID, registry.getMinBalanceForUpkeep(linkUpkeepID)); + registry.addFunds(usdUpkeepID, registry.getMinBalanceForUpkeep(usdUpkeepID)); + registry.addFunds(nativeUpkeepID, registry.getMinBalanceForUpkeep(nativeUpkeepID)); + vm.stopPrank(); } } @@ -124,7 +132,7 @@ contract AddFunds is SetUp { // it fails when the billing token is not native, but trying to pay with native function test_RevertsWhen_NativePaymentDoesntMatchBillingToken() external { - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidBillingToken.selector)); + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); registry.addFunds{value: 1}(linkUpkeepID, 0); } @@ -140,13 +148,13 @@ contract AddFunds is SetUp { } function test_anyoneCanAddFunds() public { - assertEq(registry.getBalance(linkUpkeepID), 0); + uint256 startAmount = registry.getBalance(linkUpkeepID); vm.prank(UPKEEP_ADMIN); registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), 1); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 1); vm.prank(STRANGER); registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), 2); + assertEq(registry.getBalance(linkUpkeepID), startAmount + 2); } function test_movesFundFromCorrectToken() public { @@ -154,18 +162,20 @@ contract AddFunds is SetUp { uint256 startBalanceLINK = linkToken.balanceOf(address(registry)); uint256 startBalanceUSDToken = usdToken.balanceOf(address(registry)); + uint256 startLinkUpkeepBalance = registry.getBalance(linkUpkeepID); + uint256 startUSDUpkeepBalance = registry.getBalance(usdUpkeepID); registry.addFunds(linkUpkeepID, 1); - assertEq(registry.getBalance(linkUpkeepID), 1); - assertEq(registry.getBalance(usdUpkeepID), 0); - assertEq(linkToken.balanceOf(address(registry)), startBalanceLINK + 1); - assertEq(usdToken.balanceOf(address(registry)), startBalanceUSDToken); + assertEq(registry.getBalance(linkUpkeepID), startBalanceLINK + 1); + assertEq(registry.getBalance(usdUpkeepID), startBalanceUSDToken); + assertEq(linkToken.balanceOf(address(registry)), startLinkUpkeepBalance + 1); + assertEq(usdToken.balanceOf(address(registry)), startUSDUpkeepBalance); registry.addFunds(usdUpkeepID, 2); - assertEq(registry.getBalance(linkUpkeepID), 1); - assertEq(registry.getBalance(usdUpkeepID), 2); - assertEq(linkToken.balanceOf(address(registry)), startBalanceLINK + 1); - assertEq(usdToken.balanceOf(address(registry)), startBalanceUSDToken + 2); + assertEq(registry.getBalance(linkUpkeepID), startBalanceLINK + 1); + assertEq(registry.getBalance(usdUpkeepID), startBalanceUSDToken + 2); + assertEq(linkToken.balanceOf(address(registry)), startLinkUpkeepBalance + 1); + assertEq(usdToken.balanceOf(address(registry)), startUSDUpkeepBalance + 2); } function test_emitsAnEvent() public { @@ -177,78 +187,97 @@ contract AddFunds is SetUp { } contract Withdraw is SetUp { - address internal aMockAddress = address(0x1111111111111111111111111111111111111113); + address internal aMockAddress = randomAddress(); function testLinkAvailableForPaymentReturnsLinkBalance() public { + uint256 startBalance = linkToken.balanceOf(address(registry)); + int256 startLinkAvailable = registry.linkAvailableForPayment(); + //simulate a deposit of link to the liquidity pool _mintLink(address(registry), 1e10); //check there's a balance - assertGt(linkToken.balanceOf(address(registry)), 0); + assertEq(linkToken.balanceOf(address(registry)), startBalance + 1e10); - //check the link available for payment is the link balance - assertEq(uint256(registry.linkAvailableForPayment()), linkToken.balanceOf(address(registry))); + //check the link available has increased by the same amount + assertEq(uint256(registry.linkAvailableForPayment()), uint256(startLinkAvailable) + 1e10); } - function testWithdrawLinkFeesRevertsBecauseOnlyFinanceAdminAllowed() public { + function testWithdrawLinkRevertsBecauseOnlyFinanceAdminAllowed() public { vm.expectRevert(abi.encodeWithSelector(Registry.OnlyFinanceAdmin.selector)); - registry.withdrawLinkFees(aMockAddress, 1); + registry.withdrawLink(aMockAddress, 1); } - function testWithdrawLinkFeesRevertsBecauseOfInsufficientBalance() public { + function testWithdrawLinkRevertsBecauseOfInsufficientBalance() public { vm.startPrank(FINANCE_ADMIN); // try to withdraw 1 link while there is 0 balance vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); - registry.withdrawLinkFees(aMockAddress, 1); + registry.withdrawLink(aMockAddress, 1); vm.stopPrank(); } - function testWithdrawLinkFeesRevertsBecauseOfInvalidRecipient() public { + function testWithdrawLinkRevertsBecauseOfInvalidRecipient() public { vm.startPrank(FINANCE_ADMIN); // try to withdraw 1 link while there is 0 balance vm.expectRevert(abi.encodeWithSelector(Registry.InvalidRecipient.selector)); - registry.withdrawLinkFees(ZERO_ADDRESS, 1); + registry.withdrawLink(ZERO_ADDRESS, 1); vm.stopPrank(); } - function testWithdrawLinkFeeSuccess() public { + function testWithdrawLinkSuccess() public { //simulate a deposit of link to the liquidity pool _mintLink(address(registry), 1e10); - - //check there's a balance - assertGt(linkToken.balanceOf(address(registry)), 0); + uint256 startBalance = linkToken.balanceOf(address(registry)); vm.startPrank(FINANCE_ADMIN); // try to withdraw 1 link while there is a ton of link available - registry.withdrawLinkFees(aMockAddress, 1); + registry.withdrawLink(aMockAddress, 1); vm.stopPrank(); assertEq(linkToken.balanceOf(address(aMockAddress)), 1); - assertEq(linkToken.balanceOf(address(registry)), 1e10 - 1); + assertEq(linkToken.balanceOf(address(registry)), startBalance - 1); + } + + function test_WithdrawERC20Fees_RespectsReserveAmount() public { + assertEq(registry.getBalance(usdUpkeepID), registry.getReserveAmount(address(usdToken))); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(abi.encodeWithSelector(Registry.InsufficientBalance.selector, 0, 1)); + registry.withdrawERC20Fees(address(usdToken), FINANCE_ADMIN, 1); + } + + function test_WithdrawERC20Fees_RevertsWhenAttemptingToWithdrawLINK() public { + _mintLink(address(registry), 1e10); + vm.startPrank(FINANCE_ADMIN); + vm.expectRevert(Registry.InvalidToken.selector); + registry.withdrawERC20Fees(address(linkToken), FINANCE_ADMIN, 1); // should revert + registry.withdrawLink(FINANCE_ADMIN, 1); // but using link withdraw functions succeeds } function testWithdrawERC20FeeSuccess() public { - // simulate a deposit of ERC20 to the liquidity pool + // 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); - // check there's a balance - assertGt(usdToken.balanceOf(address(registry)), 0); + // depositing shouldn't change reserve amount + assertEq(registry.getReserveAmount(address(usdToken)), startReserveAmount); vm.startPrank(FINANCE_ADMIN); - // try to withdraw 1 link while there is a ton of link available + // try to withdraw 1 USDToken registry.withdrawERC20Fees(address(usdToken), aMockAddress, 1); vm.stopPrank(); assertEq(usdToken.balanceOf(address(aMockAddress)), 1); - assertEq(usdToken.balanceOf(address(registry)), 1e10 - 1); + assertEq(usdToken.balanceOf(address(registry)), startAmount + 1e10 - 1); + assertEq(registry.getReserveAmount(address(usdToken)), startReserveAmount); } } @@ -530,7 +559,7 @@ contract SetConfig is SetUp { ); } - function testSetConfigRevertDueToInvalidBillingToken() public { + function testSetConfigRevertDueToInvalidToken() public { address[] memory billingTokens = new address[](1); billingTokens[0] = address(linkToken); @@ -543,11 +572,10 @@ contract SetConfig is SetUp { minSpend: 100_000 }); - bytes memory onchainConfigBytesWithBilling = abi.encode(cfg, billingTokens, billingConfigs); // deploy registry with OFF_CHAIN payout mode registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); - vm.expectRevert(abi.encodeWithSelector(Registry.InvalidBillingToken.selector)); + vm.expectRevert(abi.encodeWithSelector(Registry.InvalidToken.selector)); registry.setConfigTypeSafe( SIGNERS, TRANSMITTERS, @@ -560,6 +588,109 @@ contract SetConfig is SetUp { ); } + function testSetConfigWithNewTransmittersSuccess() public { + registry = deployRegistry(AutoBase.PayoutMode.OFF_CHAIN); + + (uint32 configCount, uint32 blockNumber, ) = registry.latestConfigDetails(); + assertEq(configCount, 0); + + address billingTokenAddress = address(0x1111111111111111111111111111111111111111); + address[] memory billingTokens = new address[](1); + billingTokens[0] = billingTokenAddress; + + AutomationRegistryBase2_3.BillingConfig[] memory billingConfigs = new AutomationRegistryBase2_3.BillingConfig[](1); + billingConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 5_000, + flatFeeMilliCents: 20_000, + priceFeed: 0x2222222222222222222222222222222222222222, + fallbackPrice: 2_000_000_000, // $20 + minSpend: 100_000 + }); + + bytes memory onchainConfigBytes = abi.encode(cfg); + + bytes32 configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , address[] memory signers, address[] memory transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, TRANSMITTERS); + + (configCount, blockNumber, ) = registry.latestConfigDetails(); + configDigest = _configDigestFromConfigData( + block.chainid, + address(registry), + ++configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + vm.expectEmit(); + emit ConfigSet( + blockNumber, + configDigest, + configCount, + SIGNERS, + NEW_TRANSMITTERS, + F, + onchainConfigBytes, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes + ); + + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + offchainConfigBytes, + billingTokens, + billingConfigs + ); + + (, , signers, transmitters, ) = registry.getState(); + assertEq(signers, SIGNERS); + assertEq(transmitters, NEW_TRANSMITTERS); + } + function _configDigestFromConfigData( uint256 chainId, address contractAddress, @@ -592,8 +723,11 @@ contract SetConfig is SetUp { } } +// allow NOPs to withdraw balances made before disableOffchainNOPsOffchain is called contract NOPsSettlement is SetUp { event NOPsSettledOffchain(address[] payees, uint256[] payments); + event FundsWithdrawn(uint256 indexed id, uint256 amount, address to); + event PaymentWithdrawn(address indexed transmitter, uint256 indexed amount, address indexed to, address payee); function testSettleNOPsOffchainRevertDueToUnauthorizedCaller() public { (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.ON_CHAIN); @@ -640,29 +774,7 @@ contract NOPsSettlement is SetUp { registry.addFunds(id, 1e20); // manually create a transmit so transmitters earn some rewards - AutoBase.Report memory report; - { - uint256[] memory upkeepIds = new uint256[](1); - uint256[] memory gasLimits = new uint256[](1); - bytes[] memory performDatas = new bytes[](1); - bytes[] memory triggers = new bytes[](1); - upkeepIds[0] = id; - gasLimits[0] = 1000000; - triggers[0] = _encodeConditionalTrigger( - AutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) - ); - report = AutoBase.Report(uint256(1000000000), uint256(2000000000), upkeepIds, gasLimits, triggers, performDatas); - } - bytes memory reportBytes = _encodeReport(report); - (, , bytes32 configDigest) = registry.latestConfigDetails(); - bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; - uint256[] memory signerPKs = new uint256[](2); - signerPKs[0] = SIGNING_KEY0; - signerPKs[1] = SIGNING_KEY1; - (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); - - vm.startPrank(TRANSMITTERS[0]); - registry.transmit(reportContext, reportBytes, rs, ss, vs); + _transmit(id, registry); // verify transmitters have positive balances uint256[] memory payments = new uint256[](TRANSMITTERS.length); @@ -684,13 +796,108 @@ contract NOPsSettlement is SetUp { // verify that transmitters balance has been zeroed out for (uint256 i = 0; i < TRANSMITTERS.length; i++) { - (bool active, uint8 index, uint96 balance, uint96 lastCollected, ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); assertTrue(active); assertEq(i, index); assertEq(0, balance); } } + function testSettleNOPsOffchainForDeactivatedTransmittersSuccess() public { + // deploy and configure a registry with OFF_CHAIN payout + (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); + vm.startPrank(UPKEEP_ADMIN); + usdToken.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so TRANSMITTERS earn some rewards + _transmit(id, registry); + + // TRANSMITTERS have positive balance now + // configure the registry to use NEW_TRANSMITTERS + _configureWithNewTransmitters(registry, registrar); + + _transmit(id, registry); + + // verify all transmitters have positive balances + address[] memory expectedPayees = new address[](6); + uint256[] memory expectedPayments = new uint256[](6); + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + NEW_TRANSMITTERS[i] + ); + assertTrue(active); + assertEq(i, index); + assertTrue(lastCollected > 0); + expectedPayments[i] = balance; + expectedPayees[i] = payee; + } + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, uint96 lastCollected, address payee) = registry.getTransmitterInfo( + TRANSMITTERS[i] + ); + assertFalse(active); + assertEq(i, index); + assertTrue(balance > 0); + assertTrue(lastCollected > 0); + expectedPayments[2 + i] = balance; + expectedPayees[2 + i] = payee; + } + + // verify offchain settlement will emit NOPs' balances + vm.startPrank(FINANCE_ADMIN); + + // simply expectEmit won't work here because s_deactivatedTransmitters is an enumerable set so the order of these + // deactivated transmitters is not guaranteed. To handle this, we record logs and decode data field manually. + vm.recordLogs(); + registry.settleNOPsOffchain(); + Vm.Log[] memory entries = vm.getRecordedLogs(); + + assertEq(entries.length, 1); + Vm.Log memory l = entries[0]; + assertEq(l.topics[0], keccak256("NOPsSettledOffchain(address[],uint256[])")); + (address[] memory actualPayees, uint256[] memory actualPayments) = abi.decode(l.data, (address[], uint256[])); + assertEq(actualPayees.length, 6); + assertEq(actualPayments.length, 6); + + // first 4 payees and payments are for NEW_TRANSMITTERS and they are ordered. + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + assertEq(actualPayees[i], expectedPayees[i]); + assertEq(actualPayments[i], expectedPayments[i]); + } + + // the last 2 payees and payments for TRANSMITTERS[2] and TRANSMITTERS[3] and they are not ordered + assertTrue( + (actualPayments[5] == expectedPayments[5] && + actualPayees[5] == expectedPayees[5] && + actualPayments[4] == expectedPayments[4] && + actualPayees[4] == expectedPayees[4]) || + (actualPayments[5] == expectedPayments[4] && + actualPayees[5] == expectedPayees[4] && + actualPayments[4] == expectedPayments[5] && + actualPayees[4] == expectedPayees[5]) + ); + + // verify that new transmitters balance has been zeroed out + for (uint256 i = 0; i < NEW_TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(NEW_TRANSMITTERS[i]); + assertTrue(active); + assertEq(i, index); + assertEq(0, balance); + } + // verify that deactivated transmitters (TRANSMITTERS[2] and TRANSMITTERS[3]) balance has been zeroed out + for (uint256 i = 2; i < TRANSMITTERS.length; i++) { + (bool active, uint8 index, uint96 balance, , ) = registry.getTransmitterInfo(TRANSMITTERS[i]); + assertFalse(active); + assertEq(i, index); + assertEq(0, balance); + } + } + function testDisableOffchainPaymentsRevertDueToUnauthorizedCaller() public { (Registry registry, ) = deployAndConfigureRegistryAndRegistrar(AutoBase.PayoutMode.OFF_CHAIN); @@ -707,6 +914,176 @@ contract NOPsSettlement is SetUp { assertEq(uint8(AutoBase.PayoutMode.ON_CHAIN), registry.getPayoutMode()); } + + function testSinglePerformAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (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); + vm.startPrank(UPKEEP_ADMIN); + usdToken.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually create a transmit so transmitters earn some rewards + _transmit(id, registry); + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + vm.expectEmit(); + // the upkeep spent less than minimum spending limit so upkeep admin can only withdraw upkeep balance - min spend value + emit FundsWithdrawn(id, 9.9e19, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function testMultiplePerformsAndNodesCanWithdrawOnchain() public { + // deploy and configure a registry with OFF_CHAIN payout + (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); + vm.startPrank(UPKEEP_ADMIN); + usdToken.approve(address(registry), 1e20); + registry.addFunds(id, 1e20); + + // manually call transmit so transmitters earn some rewards + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry); + } + + // disable offchain payments + _mintLink(address(registry), 1e19); + vm.prank(registry.owner()); + registry.disableOffchainPayments(); + + // manually call transmit after offchain payment is disabled + for (uint256 i = 0; i < 50; i++) { + vm.roll(100 + block.number); + _transmit(id, registry); + } + + // payees should be able to withdraw onchain + for (uint256 i = 0; i < TRANSMITTERS.length; i++) { + (, , uint96 balance, , address payee) = registry.getTransmitterInfo(TRANSMITTERS[i]); + vm.prank(payee); + vm.expectEmit(); + emit PaymentWithdrawn(TRANSMITTERS[i], balance, payee, payee); + registry.withdrawPayment(TRANSMITTERS[i], payee); + } + + // allow upkeep admin to withdraw funds + vm.startPrank(UPKEEP_ADMIN); + registry.cancelUpkeep(id); + vm.roll(100 + block.number); + uint256 balance = registry.getBalance(id); + vm.expectEmit(); + emit FundsWithdrawn(id, balance, UPKEEP_ADMIN); + registry.withdrawFunds(id, UPKEEP_ADMIN); + } + + function _transmit(uint256 id, Registry registry) internal { + uint256[] memory upkeepIds = new uint256[](1); + uint256[] memory gasLimits = new uint256[](1); + bytes[] memory performDatas = new bytes[](1); + bytes[] memory triggers = new bytes[](1); + upkeepIds[0] = id; + gasLimits[0] = 1000000; + triggers[0] = _encodeConditionalTrigger( + AutoBase.ConditionalTrigger(uint32(block.number - 1), blockhash(block.number - 1)) + ); + AutoBase.Report memory report = AutoBase.Report( + uint256(1000000000), + uint256(2000000000), + upkeepIds, + gasLimits, + triggers, + performDatas + ); + + bytes memory reportBytes = _encodeReport(report); + (, , bytes32 configDigest) = registry.latestConfigDetails(); + bytes32[3] memory reportContext = [configDigest, configDigest, configDigest]; + uint256[] memory signerPKs = new uint256[](2); + signerPKs[0] = SIGNING_KEY0; + signerPKs[1] = SIGNING_KEY1; + (bytes32[] memory rs, bytes32[] memory ss, bytes32 vs) = _signReport(reportBytes, reportContext, signerPKs); + + vm.startPrank(TRANSMITTERS[0]); + registry.transmit(reportContext, reportBytes, rs, ss, vs); + vm.stopPrank(); + } + + function _configureWithNewTransmitters(Registry registry, Registrar registrar) internal { + IERC20[] memory billingTokens = new IERC20[](1); + billingTokens[0] = IERC20(address(usdToken)); + uint256[] memory minRegistrationFees = new uint256[](billingTokens.length); + minRegistrationFees[0] = 100000000000000000000; // 100 USD + address[] memory billingTokenAddresses = new address[](billingTokens.length); + for (uint256 i = 0; i < billingTokens.length; i++) { + billingTokenAddresses[i] = address(billingTokens[i]); + } + AutomationRegistryBase2_3.BillingConfig[] + memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); + billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ + gasFeePPB: 10_000_000, // 15% + flatFeeMilliCents: 2_000, // 2 cents + priceFeed: address(USDTOKEN_USD_FEED), + fallbackPrice: 100_000_000, // $1 + minSpend: 1000000000000000000 // 1 USD + }); + + address[] memory registrars; + registrars = new address[](1); + registrars[0] = address(registrar); + AutomationRegistryBase2_3.OnchainConfig memory cfg = AutomationRegistryBase2_3.OnchainConfig({ + checkGasLimit: 5_000_000, + stalenessSeconds: 90_000, + gasCeilingMultiplier: 2, + maxPerformGas: 10_000_000, + maxCheckDataSize: 5_000, + maxPerformDataSize: 5_000, + maxRevertDataSize: 5_000, + fallbackGasPrice: 20_000_000_000, + fallbackLinkPrice: 2_000_000_000, // $20 + fallbackNativePrice: 400_000_000_000, // $4,000 + transcoder: 0xB1e66855FD67f6e85F0f0fA38cd6fBABdf00923c, + registrars: registrars, + upkeepPrivilegeManager: PRIVILEGE_MANAGER, + chainModule: address(new ChainModuleBase()), + reorgProtectionEnabled: true, + financeAdmin: FINANCE_ADMIN + }); + registry.setConfigTypeSafe( + SIGNERS, + NEW_TRANSMITTERS, + F, + cfg, + OFFCHAIN_CONFIG_VERSION, + "", + billingTokenAddresses, + billingTokenConfigs + ); + registry.setPayees(NEW_PAYEES); + } } contract WithdrawPayment is SetUp { @@ -792,7 +1169,7 @@ contract RegisterUpkeep is SetUp { } function test_RevertsWhen_TheBillingTokenIsNotConfigured() public { - vm.expectRevert(Registry.InvalidBillingToken.selector); + vm.expectRevert(Registry.InvalidToken.selector); registry.registerUpkeep( address(TARGET1), config.maxPerformGas, @@ -871,7 +1248,7 @@ contract OnTokenTransfer is SetUp { function test_RevertsWhen_TheUpkeepDoesNotUseLINKAsItsBillingToken() public { vm.startPrank(address(linkToken)); - vm.expectRevert(Registry.InvalidBillingToken.selector); + vm.expectRevert(Registry.InvalidToken.selector); registry.onTokenTransfer(UPKEEP_ADMIN, 100, abi.encode(usdUpkeepID)); } @@ -948,4 +1325,23 @@ contract BillingOverrides is SetUp { emit BillingConfigOverrideRemoved(linkUpkeepID); registry.removeBillingOverrides(linkUpkeepID); } + + function test_Happy_MaxGasPayment_WithBillingOverrides() public { + uint96 maxPayment1 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + + // Double the two billing values + AutomationRegistryBase2_3.BillingOverrides memory billingOverrides = AutomationRegistryBase2_3.BillingOverrides({ + gasFeePPB: DEFAULT_GAS_FEE_PPB * 2, + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS * 2 + }); + + vm.startPrank(PRIVILEGE_MANAGER); + registry.setBillingOverrides(linkUpkeepID, billingOverrides); + + // maxPayment2 should be greater than maxPayment1 after the overrides + // The 2 numbers should follow this: maxPayment2 - maxPayment1 == 2 * recepit.premium + // We do not apply the exact equation since we couldn't get the receipt.premium value + uint96 maxPayment2 = registry.getMaxPaymentForGas(linkUpkeepID, 0, 5_000_000, address(linkToken)); + assertGt(maxPayment2, maxPayment1); + } } 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 9f2d3ad5e5b..1706ac049a3 100644 --- a/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol +++ b/contracts/src/v0.8/automation/dev/test/BaseTest.t.sol @@ -30,6 +30,8 @@ contract BaseTest is Test { // constants address internal constant ZERO_ADDRESS = address(0); + uint32 internal constant DEFAULT_GAS_FEE_PPB = 10_000_000; + uint24 internal constant DEFAULT_FLAT_FEE_MILLI_CENTS = 2_000; // config uint8 internal constant F = 1; // number of faulty nodes @@ -61,7 +63,9 @@ contract BaseTest is Test { uint256 internal constant SIGNING_KEY3 = 0x80f14b11da94ae7f29d9a7713ea13dc838e31960a5c0f2baf45ed458947b730a; address[] internal SIGNERS = new address[](4); address[] internal TRANSMITTERS = new address[](4); + address[] internal NEW_TRANSMITTERS = new address[](4); address[] internal PAYEES = new address[](4); + address[] internal NEW_PAYEES = new address[](4); function setUp() public virtual { vm.startPrank(OWNER); @@ -87,11 +91,19 @@ contract BaseTest is Test { TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER3")))); TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER4")))); + NEW_TRANSMITTERS[0] = address(uint160(uint256(keccak256("TRANSMITTER1")))); + NEW_TRANSMITTERS[1] = address(uint160(uint256(keccak256("TRANSMITTER2")))); + NEW_TRANSMITTERS[2] = address(uint160(uint256(keccak256("TRANSMITTER5")))); + NEW_TRANSMITTERS[3] = address(uint160(uint256(keccak256("TRANSMITTER6")))); PAYEES[0] = address(100); PAYEES[1] = address(101); PAYEES[2] = address(102); PAYEES[3] = address(103); + NEW_PAYEES[0] = address(100); + NEW_PAYEES[1] = address(101); + NEW_PAYEES[2] = address(106); + NEW_PAYEES[3] = address(107); // mint funds vm.deal(OWNER, 100 ether); @@ -153,25 +165,25 @@ contract BaseTest is Test { AutomationRegistryBase2_3.BillingConfig[] memory billingTokenConfigs = new AutomationRegistryBase2_3.BillingConfig[](billingTokens.length); billingTokenConfigs[0] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 10_000_000, // 15% - flatFeeMilliCents: 2_000, // 2 cents + gasFeePPB: DEFAULT_GAS_FEE_PPB, // 15% + flatFeeMilliCents: DEFAULT_FLAT_FEE_MILLI_CENTS, // 2 cents priceFeed: address(USDTOKEN_USD_FEED), fallbackPrice: 100_000_000, // $1 - minSpend: 100000000000000000000 // 100 USD + minSpend: 1000000000000000000 // 1 USD }); billingTokenConfigs[1] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 10_000_000, // 15% - flatFeeMilliCents: 2_000, // 2 cents + 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 }); billingTokenConfigs[2] = AutomationRegistryBase2_3.BillingConfig({ - gasFeePPB: 10_000_000, // 10% - flatFeeMilliCents: 2_000, // 2 cents + 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: 5000000000000000000 // 5 LINK + minSpend: 1000000000000000000 // 1 LINK }); if (payoutMode == AutoBase.PayoutMode.OFF_CHAIN) { 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 e4d52cbec62..2ea9debaf0a 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 @@ -176,6 +176,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain { BillingTokenPaymentParams memory billingTokenParams; + uint256 nativeUSD = _getNativeUSD(hotVars); for (uint256 i = 0; i < report.upkeepIds.length; i++) { if (upkeepTransmitInfo[i].earlyChecksPassed) { if (i == 0 || upkeepTransmitInfo[i].upkeep.billingToken != upkeepTransmitInfo[i - 1].upkeep.billingToken) { @@ -189,8 +190,9 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain l1CostWei: (l1Fee * upkeepTransmitInfo[i].calldataWeight) / transmitVars.totalCalldataWeight, fastGasWei: report.fastGasWei, linkUSD: report.linkUSD, - nativeUSD: _getNativeUSD(hotVars), - billingToken: billingTokenParams, + nativeUSD: nativeUSD, + billingToken: upkeepTransmitInfo[i].upkeep.billingToken, + billingTokenParams: billingTokenParams, isTransaction: true }), report.upkeepIds[i], @@ -213,6 +215,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain // record payments s_transmitters[msg.sender].balance += transmitVars.totalReimbursement; s_hotVars.totalPremium += transmitVars.totalPremium; + s_reserveAmounts[IERC20(address(i_link))] += transmitVars.totalReimbursement + transmitVars.totalPremium; } /** @@ -245,7 +248,7 @@ contract AutomationRegistry2_3 is AutomationRegistryBase2_3, OCR2Abstract, Chain if (data.length != 32) revert InvalidDataLength(); uint256 id = abi.decode(data, (uint256)); if (s_upkeep[id].maxValidBlocknumber != UINT32_MAX) revert UpkeepCancelled(); - if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidBillingToken(); + if (address(s_upkeep[id].billingToken) != address(i_link)) revert InvalidToken(); s_upkeep[id].balance = s_upkeep[id].balance + uint96(amount); s_reserveAmounts[IERC20(address(i_link))] = s_reserveAmounts[IERC20(address(i_link))] + amount; emit FundsAdded(id, sender, uint96(amount)); 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 fe4122a8ca4..303edaa357e 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 @@ -127,8 +127,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { error IncorrectNumberOfSignatures(); error IncorrectNumberOfSigners(); error IndexOutOfRange(); - error InsufficientBalance(int256 available, uint256 requested); - error InvalidBillingToken(); + error InsufficientBalance(uint256 available, uint256 requested); error InvalidDataLength(); error InvalidFeed(); error InvalidTrigger(); @@ -136,6 +135,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { error InvalidRecipient(); error InvalidReport(); error InvalidSigner(); + error InvalidToken(); error InvalidTransmitter(); error InvalidTriggerType(); error MigrationNotPermitted(); @@ -414,6 +414,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { * @member fastGasWei the fast gas price * @member linkUSD the exchange ratio between LINK and USD * @member nativeUSD the exchange ratio between the chain's native token and USD + * @member billingToken the billing token * @member billingTokenParams the payment params specific to a particular payment token * @member isTransaction is this an eth_call or a transaction */ @@ -424,7 +425,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { uint256 fastGasWei; uint256 linkUSD; uint256 nativeUSD; - BillingTokenPaymentParams billingToken; + IERC20 billingToken; + BillingTokenPaymentParams billingTokenParams; bool isTransaction; } @@ -483,7 +485,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { event Unpaused(address account); // Event to emit when a billing configuration is set event BillingConfigSet(IERC20 indexed token, BillingConfig config); - event FeesWithdrawn(address indexed recipient, address indexed assetAddress, uint256 amount); + event FeesWithdrawn(address indexed assetAddress, address indexed recipient, uint256 amount); /** * @param link address of the LINK Token @@ -543,7 +545,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { if (upkeep.performGas < PERFORM_GAS_MIN || upkeep.performGas > s_storage.maxPerformGas) revert GasLimitOutsideRange(); if (address(s_upkeep[id].forwarder) != address(0)) revert UpkeepAlreadyExists(); - if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidBillingToken(); + if (address(s_billingConfigs[upkeep.billingToken].priceFeed) == address(0)) revert InvalidToken(); s_upkeep[id] = upkeep; s_upkeepAdmin[id] = admin; s_checkData[id] = checkData; @@ -674,13 +676,13 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { 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.billingToken.priceUSD); // has units of attoBillingToken, or "wei" + receipt.gasCharge = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.billingTokenParams.priceUSD); // has units of attoBillingToken, or "wei" receipt.gasReimbursementJuels = SafeCast.toUint96(gasPaymentHexaicosaUSD / paymentParams.linkUSD); - uint256 flatFeeHexaicosaUSD = uint256(paymentParams.billingToken.flatFeeMilliCents) * 1e21; // 1e13 for milliCents to attoUSD and 1e8 for attoUSD to hexaicosaUSD + 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.billingToken.gasFeePPB * + paymentParams.billingTokenParams.gasFeePPB * paymentParams.nativeUSD) / 1e9) + flatFeeHexaicosaUSD; - receipt.premium = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.billingToken.priceUSD); + receipt.premium = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.billingTokenParams.priceUSD); receipt.premiumJuels = SafeCast.toUint96(premiumHexaicosaUSD / paymentParams.linkUSD); return receipt; @@ -739,7 +741,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { fastGasWei: fastGasWei, linkUSD: linkUSD, nativeUSD: nativeUSD, - billingToken: paymentParams, + billingToken: billingToken, + billingTokenParams: paymentParams, isTransaction: false }) ); @@ -973,8 +976,8 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { if (upkeep.overridesEnabled) { BillingOverrides memory billingOverrides = s_billingOverrides[upkeepId]; // use the overridden configs - paymentParams.billingToken.gasFeePPB = billingOverrides.gasFeePPB; - paymentParams.billingToken.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; + paymentParams.billingTokenParams.gasFeePPB = billingOverrides.gasFeePPB; + paymentParams.billingTokenParams.flatFeeMilliCents = billingOverrides.flatFeeMilliCents; } PaymentReceipt memory receipt = _calculatePaymentAmount(hotVars, paymentParams); @@ -988,19 +991,20 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // if the user can't cover the gas fee, then direct all of the payment to the transmitter and distribute no premium to the DON payment = balance; receipt.gasReimbursementJuels = SafeCast.toUint96( - (balance * paymentParams.billingToken.priceUSD) / paymentParams.linkUSD + (balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD ); receipt.premiumJuels = 0; } else if (balance < payment) { // if the user can cover the gas fee, but not the premium, then reduce the premium payment = balance; receipt.premiumJuels = SafeCast.toUint96( - ((balance * paymentParams.billingToken.priceUSD) / paymentParams.linkUSD) - receipt.gasReimbursementJuels + ((balance * paymentParams.billingTokenParams.priceUSD) / paymentParams.linkUSD) - receipt.gasReimbursementJuels ); } s_upkeep[upkeepId].balance -= payment; s_upkeep[upkeepId].amountSpent += payment; + s_reserveAmounts[paymentParams.billingToken] -= payment; return receipt; } @@ -1069,7 +1073,7 @@ abstract contract AutomationRegistryBase2_3 is ConfirmedOwner { // if LINK is a billing option, payout mode must be ON_CHAIN if (address(token) == address(i_link) && mode == PayoutMode.OFF_CHAIN) { - revert InvalidBillingToken(); + revert InvalidToken(); } if (address(token) == ZERO_ADDRESS || address(config.priceFeed) == ZERO_ADDRESS) { revert ZeroAddressNotAllowed(); 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 693b51942cb..0078f47400b 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 @@ -76,7 +76,7 @@ contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { if (msg.value != 0) { if (upkeep.billingToken != IERC20(i_wrappedNativeToken)) { - revert InvalidBillingToken(); + revert InvalidToken(); } amount = SafeCast.toUint96(msg.value); } @@ -205,34 +205,51 @@ contract AutomationRegistryLogicB2_3 is AutomationRegistryBase2_3, Chainable { } /** - * @notice LINK available to withdraw by the finance team + * @notice returns the size of the LINK liquidity pool # @dev LINK max supply < 2^96, so casting to int256 is safe */ function linkAvailableForPayment() public view returns (int256) { return int256(i_link.balanceOf(address(this))) - int256(s_reserveAmounts[IERC20(address(i_link))]); } - function withdrawLinkFees(address to, uint256 amount) external { + /** + * @notice withdraws excess LINK from the liquidity pool + * @param to the address to send the fees to + * @param amount the amount to withdraw + */ + function withdrawLink(address to, uint256 amount) external { _onlyFinanceAdminAllowed(); if (to == ZERO_ADDRESS) revert InvalidRecipient(); int256 available = linkAvailableForPayment(); - if (available < 0 || amount > uint256(available)) revert InsufficientBalance(available, amount); + if (available < 0) { + revert InsufficientBalance(0, amount); + } else if (amount > uint256(available)) { + revert InsufficientBalance(uint256(available), amount); + } bool transferStatus = i_link.transfer(to, amount); if (!transferStatus) { revert TransferFailed(); } - emit FeesWithdrawn(to, address(i_link), amount); + emit FeesWithdrawn(address(i_link), to, amount); } - function withdrawERC20Fees(address assetAddress, address to, uint256 amount) external { + /** + * @notice withdraws non-LINK fees earned by the contract + * @param asset the asset to withdraw + * @param to the address to send the fees to + * @param amount the amount to withdraw + */ + function withdrawERC20Fees(IERC20 asset, address to, uint256 amount) external { _onlyFinanceAdminAllowed(); if (to == ZERO_ADDRESS) revert InvalidRecipient(); + if (address(asset) == address(i_link)) revert InvalidToken(); + uint256 available = asset.balanceOf(address(this)) - s_reserveAmounts[asset]; + if (amount > available) revert InsufficientBalance(available, amount); - IERC20(assetAddress).safeTransfer(to, amount); - - emit FeesWithdrawn(to, assetAddress, amount); + asset.safeTransfer(to, amount); + emit FeesWithdrawn(address(asset), to, amount); } /** diff --git a/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol index 979cc6138ac..c4d577134c2 100644 --- a/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol +++ b/contracts/src/v0.8/automation/testhelpers/SimpleLogUpkeepCounter.sol @@ -3,14 +3,16 @@ pragma solidity 0.8.6; import {ILogAutomation, Log} from "../interfaces/ILogAutomation.sol"; +import "../interfaces/StreamsLookupCompatibleInterface.sol"; struct CheckData { uint256 checkBurnAmount; uint256 performBurnAmount; bytes32 eventSig; + string[] feeds; } -contract SimpleLogUpkeepCounter is ILogAutomation { +contract SimpleLogUpkeepCounter is ILogAutomation, StreamsLookupCompatibleInterface { event PerformingUpkeep( address indexed from, uint256 initialBlock, @@ -27,36 +29,77 @@ contract SimpleLogUpkeepCounter is ILogAutomation { uint256 public initialBlock; uint256 public counter; uint256 public timeToPerform; - bool public isRecovered; + bool internal isRecovered; + bool public isStreamsLookup; + bool public shouldRetryOnError; + string public feedParamKey = "feedIDs"; + string public timeParamKey = "timestamp"; - constructor() { + constructor(bool _isStreamsLookup) { previousPerformBlock = 0; lastBlock = block.number; initialBlock = 0; counter = 0; + isStreamsLookup = _isStreamsLookup; } function _checkDataConfig(CheckData memory) external {} + function setTimeParamKey(string memory timeParam) external { + timeParamKey = timeParam; + } + + function setFeedParamKey(string memory feedParam) external { + feedParamKey = feedParam; + } + + function setShouldRetryOnErrorBool(bool value) public { + shouldRetryOnError = value; + } + function checkLog(Log calldata log, bytes calldata checkData) external view override returns (bool, bytes memory) { - (uint256 checkBurnAmount, uint256 performBurnAmount, bytes32 eventSig) = abi.decode( - checkData, - (uint256, uint256, bytes32) - ); + CheckData memory _checkData = abi.decode(checkData, (CheckData)); uint256 startGas = gasleft(); bytes32 dummyIndex = blockhash(block.number - 1); bool dummy; // burn gas - if (checkBurnAmount > 0) { - while (startGas - gasleft() < checkBurnAmount) { + if (_checkData.checkBurnAmount > 0) { + while (startGas - gasleft() < _checkData.checkBurnAmount) { dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); } } - if (log.topics[2] == eventSig) { - return (true, abi.encode(log, block.number, checkData)); + bytes[] memory values = new bytes[](2); + values[0] = abi.encode(0x00); + values[1] = abi.encode(0x00); + bytes memory extraData = abi.encode(log, block.number, checkData); + if (log.topics[2] == _checkData.eventSig) { + if (isStreamsLookup) { + revert StreamsLookup(feedParamKey, _checkData.feeds, timeParamKey, block.timestamp, extraData); + } + return (true, abi.encode(values, extraData)); } - return (false, abi.encode(log, block.number, checkData)); + return (false, abi.encode(values, extraData)); + } + + function checkCallback( + bytes[] memory values, + bytes memory extraData + ) external view override returns (bool, bytes memory) { + // do sth about the chainlinkBlob data in values and extraData + bytes memory performData = abi.encode(values, extraData); + return (true, performData); + } + + function checkErrorHandler( + uint256 errCode, + bytes memory extraData + ) external view override returns (bool upkeepNeeded, bytes memory performData) { + bytes[] memory values = new bytes[](2); + values[0] = abi.encode(errCode); + values[1] = abi.encode(extraData); + bytes memory returnData = abi.encode(values, extraData); + return (shouldRetryOnError, returnData); } function performUpkeep(bytes calldata performData) external override { @@ -66,22 +109,23 @@ contract SimpleLogUpkeepCounter is ILogAutomation { lastBlock = block.number; counter = counter + 1; previousPerformBlock = lastBlock; - (Log memory log, uint256 checkBlock, bytes memory extraData) = abi.decode(performData, (Log, uint256, bytes)); + (, bytes memory extraData) = abi.decode(performData, (bytes[], bytes)); + (Log memory log, uint256 checkBlock, bytes memory checkData) = abi.decode(extraData, (Log, uint256, bytes)); timeToPerform = block.timestamp - log.timestamp; isRecovered = false; if (checkBlock != log.blockNumber) { isRecovered = true; } - (uint256 checkBurnAmount, uint256 performBurnAmount, bytes32 eventSig) = abi.decode( - extraData, - (uint256, uint256, bytes32) - ); + CheckData memory _checkData = abi.decode(checkData, (CheckData)); uint256 startGas = gasleft(); bytes32 dummyIndex = blockhash(block.number - 1); bool dummy; + if (log.topics[2] != _checkData.eventSig) { + revert("Invalid event signature"); + } // burn gas - if (performBurnAmount > 0) { - while (startGas - gasleft() < performBurnAmount) { + if (_checkData.performBurnAmount > 0) { + while (startGas - gasleft() < _checkData.performBurnAmount) { dummy = dummy && dummyMap[dummyIndex]; // arbitrary storage reads dummyIndex = keccak256(abi.encode(dummyIndex, address(this))); } diff --git a/contracts/src/v0.7/tests/UpkeepAutoFunder.sol b/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol similarity index 64% rename from contracts/src/v0.7/tests/UpkeepAutoFunder.sol rename to contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol index 9de92d03ff8..263aad5492f 100644 --- a/contracts/src/v0.7/tests/UpkeepAutoFunder.sol +++ b/contracts/src/v0.8/automation/testhelpers/UpkeepAutoFunder.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.8.0; -import "../KeeperCompatible.sol"; -import "../interfaces/LinkTokenInterface.sol"; -import "../interfaces/KeeperRegistryInterface.sol"; -import "../ConfirmedOwner.sol"; +import {AutomationCompatible} from "../AutomationCompatible.sol"; +import {LinkTokenInterface} from "../../shared/interfaces/LinkTokenInterface.sol"; +import {ConfirmedOwner} from "../../shared/access/ConfirmedOwner.sol"; +import {AutomationRegistryBaseInterface} from "../interfaces/v2_0/AutomationRegistryInterface2_0.sol"; -contract UpkeepAutoFunder is KeeperCompatible, ConfirmedOwner { +contract UpkeepAutoFunder is AutomationCompatible, ConfirmedOwner { bool public s_isEligible; bool public s_shouldCancel; uint256 public s_upkeepId; uint96 public s_autoFundLink; LinkTokenInterface public immutable LINK; - KeeperRegistryBaseInterface public immutable s_keeperRegistry; + AutomationRegistryBaseInterface public immutable s_keeperRegistry; constructor(address linkAddress, address registryAddress) ConfirmedOwner(msg.sender) { LINK = LinkTokenInterface(linkAddress); - s_keeperRegistry = KeeperRegistryBaseInterface(registryAddress); + s_keeperRegistry = AutomationRegistryBaseInterface(registryAddress); s_isEligible = false; s_shouldCancel = false; @@ -40,12 +40,9 @@ contract UpkeepAutoFunder is KeeperCompatible, ConfirmedOwner { s_upkeepId = value; } - function checkUpkeep(bytes calldata data) - external - override - cannotExecute - returns (bool callable, bytes calldata executedata) - { + function checkUpkeep( + bytes calldata data + ) external override cannotExecute returns (bool callable, bytes calldata executedata) { return (s_isEligible, data); } diff --git a/contracts/src/v0.7/tests/UpkeepMock.sol b/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol similarity index 93% rename from contracts/src/v0.7/tests/UpkeepMock.sol rename to contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol index a4708eb1cad..392700ea3d6 100644 --- a/contracts/src/v0.7/tests/UpkeepMock.sol +++ b/contracts/src/v0.8/automation/testhelpers/UpkeepMock.sol @@ -1,9 +1,9 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.8.0; -import "../KeeperCompatible.sol"; +import {AutomationCompatible} from "../AutomationCompatible.sol"; -contract UpkeepMock is KeeperCompatible { +contract UpkeepMock is AutomationCompatible { bool public shouldRevertCheck; bool public canCheck; bool public canPerform; @@ -56,7 +56,7 @@ contract UpkeepMock is KeeperCompatible { } function checkUpkeep( - bytes calldata data + bytes calldata ) external override cannotExecute returns (bool callable, bytes memory executedata) { require(!shouldRevertCheck, checkRevertReason); uint256 startGas = gasleft(); diff --git a/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol b/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol new file mode 100644 index 00000000000..1d140ccf6d0 --- /dev/null +++ b/contracts/src/v0.8/automation/testhelpers/UpkeepReverter.sol @@ -0,0 +1,17 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {AutomationCompatible} from "../AutomationCompatible.sol"; + +contract UpkeepReverter is AutomationCompatible { + function checkUpkeep( + bytes calldata data + ) public view override cannotExecute returns (bool callable, bytes calldata executedata) { + require(false, "!working"); + return (true, data); + } + + function performUpkeep(bytes calldata) external pure override { + require(false, "!working"); + } +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/BasicConsumer.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/BasicConsumer.sol new file mode 100644 index 00000000000..7004b53416a --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/BasicConsumer.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Consumer} from "./Consumer.sol"; + +contract BasicConsumer is Consumer { + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; + } +} diff --git a/contracts/src/v0.6/tests/Consumer.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/Consumer.sol similarity index 58% rename from contracts/src/v0.6/tests/Consumer.sol rename to contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/Consumer.sol index 1e49bcef18f..0d01778e19e 100644 --- a/contracts/src/v0.6/tests/Consumer.sol +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/Consumer.sol @@ -1,14 +1,17 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.8.0; -import "../ChainlinkClient.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../../Chainlink.sol"; contract Consumer is ChainlinkClient { - bytes32 internal specId; + using Chainlink for Chainlink.Request; + + bytes32 internal s_specId; bytes32 public currentPrice; event RequestFulfilled( - bytes32 indexed requestId, // User-defined ID + bytes32 indexed requestId, // User-defined ID bytes32 indexed price ); @@ -17,12 +20,12 @@ contract Consumer is ChainlinkClient { } function requestEthereumPriceByCallback(string memory _currency, uint256 _payment, address _callback) public { - Chainlink.Request memory req = buildChainlinkRequest(specId, _callback, this.fulfill.selector); - req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, _callback, this.fulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); string[] memory path = new string[](1); path[0] = _currency; - req.addStringArray("path", path); - sendChainlinkRequest(req, _payment); + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); } function cancelRequest( @@ -37,20 +40,16 @@ contract Consumer is ChainlinkClient { } function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress()); + LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); } function addExternalRequest(address _oracle, bytes32 _requestId) external { - addChainlinkExternalRequest(_oracle, _requestId); + _addChainlinkExternalRequest(_oracle, _requestId); } - function fulfill(bytes32 _requestId, bytes32 _price) - public - recordChainlinkFulfillment(_requestId) - { + function fulfill(bytes32 _requestId, bytes32 _price) public recordChainlinkFulfillment(_requestId) { emit RequestFulfilled(_requestId, _price); currentPrice = _price; } - } diff --git a/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/EmptyOracle.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/EmptyOracle.sol new file mode 100644 index 00000000000..2abe393151e --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/EmptyOracle.sol @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ChainlinkRequestInterface} from "../../../../interfaces/ChainlinkRequestInterface.sol"; +import {OracleInterface} from "../../../../interfaces/OracleInterface.sol"; + +/* solhint-disable no-empty-blocks */ +contract EmptyOracle is ChainlinkRequestInterface, OracleInterface { + function cancelOracleRequest(bytes32, uint256, bytes4, uint256) external override {} + function fulfillOracleRequest(bytes32, uint256, address, bytes4, uint256, bytes32) external override returns (bool) {} + function getAuthorizationStatus(address) external pure returns (bool) { + return false; + } + function onTokenTransfer(address, uint256, bytes calldata) external pure {} + function oracleRequest( + address, + uint256, + bytes32, + address, + bytes4, + uint256, + uint256, + bytes calldata + ) external override {} + function setFulfillmentPermission(address, bool) external {} + function withdraw(address, uint256) external override {} + function withdrawable() external view override returns (uint256) {} +} diff --git a/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/GasGuzzlingConsumer.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/GasGuzzlingConsumer.sol new file mode 100644 index 00000000000..54ff0e30e66 --- /dev/null +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/GasGuzzlingConsumer.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {Consumer} from "./Consumer.sol"; +import {Chainlink} from "../../../../Chainlink.sol"; + +contract GasGuzzlingConsumer is Consumer { + using Chainlink for Chainlink.Request; + + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; + } + + function gassyRequestEthereumPrice(uint256 _payment) public { + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyFulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + string[] memory path = new string[](1); + path[0] = "USD"; + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); + } + + function gassyFulfill(bytes32 _requestId, bytes32) public recordChainlinkFulfillment(_requestId) { + while (true) {} + } + + function gassyMultiWordRequest(uint256 _payment) public { + Chainlink.Request memory req = _buildChainlinkRequest(s_specId, address(this), this.gassyMultiWordFulfill.selector); + req._add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD,EUR,JPY"); + string[] memory path = new string[](1); + path[0] = "USD"; + req._addStringArray("path", path); + _sendChainlinkRequest(req, _payment); + } + + function gassyMultiWordFulfill(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { + while (true) {} + } +} diff --git a/contracts/src/v0.6/tests/MaliciousMultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousMultiWordConsumer.sol similarity index 53% rename from contracts/src/v0.6/tests/MaliciousMultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousMultiWordConsumer.sol index cd36836df12..272361f2dda 100644 --- a/contracts/src/v0.6/tests/MaliciousMultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousMultiWordConsumer.sol @@ -1,26 +1,24 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; +pragma solidity ^0.8.0; -import "../ChainlinkClient.sol"; -import "../vendor/SafeMathChainlink.sol"; +import {ChainlinkClient} from "../../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../../Chainlink.sol"; contract MaliciousMultiWordConsumer is ChainlinkClient { - using SafeMathChainlink for uint256; - - uint256 constant private ORACLE_PAYMENT = 1 * LINK; - uint256 private expiration; + uint256 private constant ORACLE_PAYMENT = 1 ether; + uint256 private s_expiration; constructor(address _link, address _oracle) public payable { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); } receive() external payable {} // solhint-disable-line no-empty-blocks function requestData(bytes32 _id, bytes memory _callbackFunc) public { - Chainlink.Request memory req = buildChainlinkRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); - expiration = now.add(5 minutes); // solhint-disable-line not-rely-on-time - sendChainlinkRequest(req, ORACLE_PAYMENT); + Chainlink.Request memory req = _buildChainlinkRequest(_id, address(this), bytes4(keccak256(_callbackFunc))); + s_expiration = block.timestamp + 5 minutes; // solhint-disable-line not-rely-on-time + _sendChainlinkRequest(req, ORACLE_PAYMENT); } function assertFail(bytes32, bytes memory) public pure { @@ -28,30 +26,26 @@ contract MaliciousMultiWordConsumer is ChainlinkClient { } function cancelRequestOnFulfill(bytes32 _requestId, bytes memory) public { - cancelChainlinkRequest( - _requestId, - ORACLE_PAYMENT, - this.cancelRequestOnFulfill.selector, - expiration); + _cancelChainlinkRequest(_requestId, ORACLE_PAYMENT, this.cancelRequestOnFulfill.selector, s_expiration); } function remove() public { - selfdestruct(address(0)); + selfdestruct(payable(address(0))); } function stealEthCall(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - (bool success,) = address(this).call.value(100)(""); // solhint-disable-line avoid-call-value + (bool success, ) = address(this).call{value: 100}(""); // solhint-disable-line avoid-call-value require(success, "Call failed"); } function stealEthSend(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { // solhint-disable-next-line check-send-result - bool success = address(this).send(100); // solhint-disable-line multiple-sends + bool success = payable(address(this)).send(100); // solhint-disable-line multiple-sends require(success, "Send failed"); } function stealEthTransfer(bytes32 _requestId, bytes memory) public recordChainlinkFulfillment(_requestId) { - address(this).transfer(100); + payable(address(this)).transfer(100); } function doesNothing(bytes32, bytes memory) public pure {} // solhint-disable-line no-empty-blocks diff --git a/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousRequester.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousRequester.sol index c1ce74dfa18..9b19653722c 100644 --- a/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousRequester.sol +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousRequester.sol @@ -8,7 +8,7 @@ contract MaliciousRequester is MaliciousChainlinked { uint256 private constant ORACLE_PAYMENT = 1 ether; uint256 private s_expiration; - constructor(address _link, address _oracle) public { + constructor(address _link, address _oracle) { setLinkToken(_link); setOracle(_oracle); } diff --git a/contracts/src/v0.7/tests/MultiWordConsumer.sol b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MultiWordConsumer.sol similarity index 63% rename from contracts/src/v0.7/tests/MultiWordConsumer.sol rename to contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MultiWordConsumer.sol index 7cadbb24db3..ce2bf1907c5 100644 --- a/contracts/src/v0.7/tests/MultiWordConsumer.sol +++ b/contracts/src/v0.8/operatorforwarder/dev/tests/testhelpers/MultiWordConsumer.sol @@ -1,12 +1,12 @@ -pragma solidity ^0.7.0; +pragma solidity ^0.8.0; -import "../ChainlinkClient.sol"; -import "../Chainlink.sol"; +import {ChainlinkClient, ChainlinkRequestInterface, LinkTokenInterface} from "../../../../ChainlinkClient.sol"; +import {Chainlink} from "../../../../Chainlink.sol"; contract MultiWordConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; - bytes32 internal specId; + bytes32 internal s_specId; bytes public currentPrice; bytes32 public usd; @@ -31,28 +31,24 @@ contract MultiWordConsumer is ChainlinkClient { uint256 jpy ); - constructor( - address _link, - address _oracle, - bytes32 _specId - ) public { - setChainlinkToken(_link); - setChainlinkOracle(_oracle); - specId = _specId; + constructor(address _link, address _oracle, bytes32 _specId) { + _setChainlinkToken(_link); + _setChainlinkOracle(_oracle); + s_specId = _specId; } function setSpecID(bytes32 _specId) public { - specId = _specId; + s_specId = _specId; } - function requestEthereumPrice(string memory _currency, uint256 _payment) public { - Chainlink.Request memory req = buildOperatorRequest(specId, this.fulfillBytes.selector); - sendOperatorRequest(req, _payment); + function requestEthereumPrice(string memory, uint256 _payment) public { + Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillBytes.selector); + _sendOperatorRequest(req, _payment); } - function requestMultipleParameters(string memory _currency, uint256 _payment) public { - Chainlink.Request memory req = buildOperatorRequest(specId, this.fulfillMultipleParameters.selector); - sendOperatorRequest(req, _payment); + function requestMultipleParameters(string memory, uint256 _payment) public { + Chainlink.Request memory req = _buildOperatorRequest(s_specId, this.fulfillMultipleParameters.selector); + _sendOperatorRequest(req, _payment); } function requestMultipleParametersWithCustomURLs( @@ -64,14 +60,17 @@ contract MultiWordConsumer is ChainlinkClient { string memory _pathJPY, uint256 _payment ) public { - Chainlink.Request memory req = buildOperatorRequest(specId, this.fulfillMultipleParametersWithCustomURLs.selector); - req.add("urlUSD", _urlUSD); - req.add("pathUSD", _pathUSD); - req.add("urlEUR", _urlEUR); - req.add("pathEUR", _pathEUR); - req.add("urlJPY", _urlJPY); - req.add("pathJPY", _pathJPY); - sendOperatorRequest(req, _payment); + Chainlink.Request memory req = _buildOperatorRequest( + s_specId, + this.fulfillMultipleParametersWithCustomURLs.selector + ); + req._add("urlUSD", _urlUSD); + req._add("pathUSD", _pathUSD); + req._add("urlEUR", _urlEUR); + req._add("pathEUR", _pathEUR); + req._add("urlJPY", _urlJPY); + req._add("pathJPY", _pathJPY); + _sendOperatorRequest(req, _payment); } function cancelRequest( @@ -86,12 +85,12 @@ contract MultiWordConsumer is ChainlinkClient { } function withdrawLink() public { - LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress()); + LinkTokenInterface _link = LinkTokenInterface(_chainlinkTokenAddress()); require(_link.transfer(msg.sender, _link.balanceOf(address(this))), "Unable to transfer"); } function addExternalRequest(address _oracle, bytes32 _requestId) external { - addChainlinkExternalRequest(_oracle, _requestId); + _addChainlinkExternalRequest(_oracle, _requestId); } function fulfillMultipleParameters( @@ -124,6 +123,6 @@ contract MultiWordConsumer is ChainlinkClient { } function publicGetNextRequestCount() external view returns (uint256) { - return getNextRequestCount(); + return _getNextRequestCount(); } } diff --git a/contracts/src/v0.7/tests/ConfirmedOwnerTestHelper.sol b/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol similarity index 71% rename from contracts/src/v0.7/tests/ConfirmedOwnerTestHelper.sol rename to contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol index 99a077074df..47ecbb0cd1f 100644 --- a/contracts/src/v0.7/tests/ConfirmedOwnerTestHelper.sol +++ b/contracts/src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.7.0; +pragma solidity ^0.8.0; -import "../ConfirmedOwner.sol"; +import {ConfirmedOwner} from "../../access/ConfirmedOwner.sol"; contract ConfirmedOwnerTestHelper is ConfirmedOwner { event Here(); diff --git a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol index aa75a1170c7..5876ddfc2fa 100644 --- a/contracts/src/v0.8/shared/token/ERC677/ERC677.sol +++ b/contracts/src/v0.8/shared/token/ERC677/ERC677.sol @@ -4,19 +4,16 @@ pragma solidity ^0.8.0; import {IERC677} from "./IERC677.sol"; import {IERC677Receiver} from "../../interfaces/IERC677Receiver.sol"; -import {Address} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/utils/Address.sol"; import {ERC20} from "../../../vendor/openzeppelin-solidity/v4.8.3/contracts/token/ERC20/ERC20.sol"; contract ERC677 is IERC677, ERC20 { - using Address for address; - constructor(string memory name, string memory symbol) ERC20(name, symbol) {} /// @inheritdoc IERC677 function transferAndCall(address to, uint256 amount, bytes memory data) public returns (bool success) { super.transfer(to, amount); emit Transfer(msg.sender, to, amount, data); - if (to.isContract()) { + if (to.code.length > 0) { IERC677Receiver(to).onTokenTransfer(msg.sender, amount, data); } return true; diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol index 38b6fb57983..932d35006c4 100644 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/Paymaster.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.19; import {IPaymaster} from "../../../vendor/entrypoint/interfaces/IPaymaster.sol"; import {SCALibrary} from "./SCALibrary.sol"; diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol index 6a11eecfe00..589c55f5b3b 100644 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SCA.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT -/// TODO: decide on a compiler version. Must not be dynamic, and must be > 0.8.12. -pragma solidity 0.8.15; +pragma solidity 0.8.19; import {IAccount} from "../../../vendor/entrypoint/interfaces/IAccount.sol"; import {SCALibrary} from "./SCALibrary.sol"; diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol index 35d666a2d3d..095a3428ef4 100644 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.19; library SCALibrary { // keccak256("EIP712Domain(uint256 chainId, address verifyingContract)"); diff --git a/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol b/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol index bb0f2dbde63..f27c8e15cf6 100644 --- a/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol +++ b/contracts/src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.19; contract SmartContractAccountFactory { event ContractCreated(address scaAddress); diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol b/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol index 92e50b806fe..5851c86581e 100644 --- a/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol +++ b/contracts/src/v0.8/transmission/dev/testhelpers/Greeter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.19; /// @dev Ownerless greeter contract. contract Greeter { diff --git a/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol b/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol index 014f296f077..b080484d8cc 100644 --- a/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol +++ b/contracts/src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.15; +pragma solidity ^0.8.19; import {SCA} from "../ERC-4337/SCA.sol"; import {SmartContractAccountFactory} from "../ERC-4337/SmartContractAccountFactory.sol"; diff --git a/contracts/test/v0.8/foundry/BaseTest.t.sol b/contracts/src/v0.8/transmission/test/BaseTest.t.sol similarity index 100% rename from contracts/test/v0.8/foundry/BaseTest.t.sol rename to contracts/src/v0.8/transmission/test/BaseTest.t.sol diff --git a/contracts/test/v0.8/foundry/transmission/EIP_712_1014_4337.t.sol b/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol similarity index 91% rename from contracts/test/v0.8/foundry/transmission/EIP_712_1014_4337.t.sol rename to contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol index 8e43527af53..fdfe190de26 100644 --- a/contracts/test/v0.8/foundry/transmission/EIP_712_1014_4337.t.sol +++ b/contracts/src/v0.8/transmission/test/EIP_712_1014_4337.t.sol @@ -1,20 +1,22 @@ -pragma solidity ^0.8.15; - -import "../BaseTest.t.sol"; -import "../../../../src/v0.8/transmission/dev/ERC-4337/SmartContractAccountFactory.sol"; -import "../../../../src/v0.8/transmission/dev/testhelpers/SmartContractAccountHelper.sol"; -import "../../../../src/v0.8/transmission/dev/ERC-4337/SCA.sol"; -import "../../../../src/v0.8/transmission/dev/testhelpers/Greeter.sol"; -import "../../../../src/v0.8/transmission/dev/ERC-4337/Paymaster.sol"; -import "../../../../src/v0.8/vendor/entrypoint/interfaces/UserOperation.sol"; -import "../../../../src/v0.8/vendor/entrypoint/core/EntryPoint.sol"; -import "../../../../src/v0.8/vendor/entrypoint/interfaces/IEntryPoint.sol"; -import "../../../../src/v0.8/transmission/dev/ERC-4337/SCALibrary.sol"; -import "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import "../../../../src/v0.8/shared/interfaces/LinkTokenInterface.sol"; -import "../../../../src/v0.8/vrf/mocks/VRFCoordinatorMock.sol"; -import "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import "../../../../src/v0.8/vrf/testhelpers/VRFConsumer.sol"; +pragma solidity 0.8.19; + +import "../../shared/interfaces/LinkTokenInterface.sol"; + +import "./BaseTest.t.sol"; +import "../dev/ERC-4337/SmartContractAccountFactory.sol"; +import "../dev/testhelpers/SmartContractAccountHelper.sol"; +import "../dev/ERC-4337/SCA.sol"; +import "../dev/testhelpers/Greeter.sol"; +import "../dev/ERC-4337/Paymaster.sol"; +import "../../transmission/dev/ERC-4337/SCALibrary.sol"; +import "../../mocks/MockLinkToken.sol"; +import "../../tests/MockV3Aggregator.sol"; +import "../../vrf/mocks/VRFCoordinatorMock.sol"; +import "../../vrf/testhelpers/VRFConsumer.sol"; + +import "../../vendor/entrypoint/interfaces/UserOperation.sol"; +import "../../vendor/entrypoint/core/EntryPoint.sol"; +import "../../vendor/entrypoint/interfaces/IEntryPoint.sol"; /*--------------------------------------------------------------------------------------------------------------------+ | EIP 712 + 1014 + 4337 | @@ -27,7 +29,7 @@ import "../../../../src/v0.8/vrf/testhelpers/VRFConsumer.sol"; | | | The below tests illustrate end-user flows for interacting with this meta-transaction system. For users with | | existing Smart Contract Accounts (SCAs), they simply sign off on the operation, after which the executor | -| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then exectute the transaction | +| invokes the EntryPoint that authorizes the operation on the end-user's SCA, and then execute the transaction | | as the SCA. For users without existing SCAs, EIP-1014 ensures that the address of an SCA can be known in advance, | | so users can sign-off on transactions that will be executed by a not-yet-deployed SCA. The EntryPoint contract | | takes advantage of this functionality and allows for the SCA to be created in the same user operation that invokes | @@ -40,12 +42,6 @@ import "../../../../src/v0.8/vrf/testhelpers/VRFConsumer.sol"; | | -+---------------------------------------------------------------------------------------------------------------------*/ -/*----------------------------+ -| TESTS | -| ________________ | -| | -+----------------------------*/ - contract EIP_712_1014_4337 is BaseTest { event RandomnessRequest(address indexed sender, bytes32 indexed keyHash, uint256 indexed seed, uint256 fee); @@ -69,7 +65,7 @@ contract EIP_712_1014_4337 is BaseTest { // Impersonate a LINK whale. changePrank(LINK_WHALE); - // Create simople greeter contract. + // Create simple greeter contract. greeter = new Greeter(); assertEq("", greeter.getGreeting()); @@ -178,7 +174,7 @@ contract EIP_712_1014_4337 is BaseTest { encodedGreetingCall ); - // Construct the user opeartion. + // Construct the user operation. UserOperation memory op = UserOperation({ sender: toDeployAddress, nonce: 0, @@ -322,7 +318,7 @@ contract EIP_712_1014_4337 is BaseTest { topupAmount: 10 ether }); - // Construct the user opeartion. + // Construct the user operation. UserOperation memory op = UserOperation({ sender: toDeployAddress, nonce: 0, @@ -344,7 +340,7 @@ contract EIP_712_1014_4337 is BaseTest { // Deposit funds for the transaction. entryPoint.depositTo{value: 10 ether}(address(paymaster)); - // Assert correct log is emmitted for the end-contract vrf request. + // Assert correct log is emitted for the end-contract vrf request. vm.expectEmit(true, true, true, true); emit RandomnessRequest( address(vrfConsumer), diff --git a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol index 8feff16942f..078d934e5e3 100644 --- a/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol @@ -30,6 +30,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i uint256 public immutable SUBSCRIPTION_ID; LinkTokenInterface internal immutable i_link; + AggregatorV3Interface internal immutable i_link_native_feed; error LinkAlreadySet(); error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM); @@ -80,13 +81,6 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // fallback to fallbackWeiPerUnitLink. uint32 private s_stalenessSeconds; - AggregatorV3Interface public s_linkNativeFeed; - - /// @dev padding to make sure that the next variable is at a new storage slot - uint64 private s_padding; - /* Storage Slot 5: END */ - - /* Storage Slot 6: BEGIN */ // s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords // function. The cost for this gas is passed to the user. uint32 private s_wrapperGasOverhead; @@ -115,16 +109,18 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // charges for link payment. uint32 private s_fulfillmentFlatFeeLinkDiscountPPM; - // s_wrapperNativePremiumPercentage is the premium ratio in percentage for native payment. For example, a value of 0 - // indicates no premium. A value of 15 indicates a 15 percent premium. - uint8 private s_wrapperNativePremiumPercentage; + // s_coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for native payment. + // For example, a value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. + // Wrapper has no premium. This premium is for VRFCoordinator. + uint8 private s_coordinatorNativePremiumPercentage; - // s_wrapperLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a value of 0 - // indicates no premium. A value of 15 indicates a 15 percent premium. - uint8 private s_wrapperLinkPremiumPercentage; + // s_coordinatorLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a + // value of 0 indicates no premium. A value of 15 indicates a 15 percent premium. + // Wrapper has no premium. This premium is for VRFCoordinator. + uint8 private s_coordinatorLinkPremiumPercentage; - // 10 bytes left - /* Storage Slot 6: END */ + // 6 bytes left + /* Storage Slot 5: END */ struct Callback { address callbackAddress; @@ -135,9 +131,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // GasPrice is unlikely to be more than 14 ETH on most chains uint64 requestGasPrice; } - /* Storage Slot 7: BEGIN */ + /* Storage Slot 6: BEGIN */ mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks; - /* Storage Slot 7: END */ + /* Storage Slot 6: END */ constructor( address _link, @@ -145,14 +141,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume address _coordinator, uint256 _subId ) VRFConsumerBaseV2Plus(_coordinator) { - if (_link == address(0)) { - revert ZeroAddress(); - } i_link = LinkTokenInterface(_link); + i_link_native_feed = AggregatorV3Interface(_linkNativeFeed); - if (_linkNativeFeed != address(0)) { - s_linkNativeFeed = AggregatorV3Interface(_linkNativeFeed); - } if (_subId == 0) { revert SubscriptionIdMissing(); } @@ -168,16 +159,6 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume SUBSCRIPTION_ID = _subId; } - /** - * @notice set link native feed to be used by this wrapper - * @param linkNativeFeed address of the link native feed - */ - function setLinkNativeFeed(address linkNativeFeed) external onlyOwner { - s_linkNativeFeed = AggregatorV3Interface(linkNativeFeed); - - emit LinkNativeFeedSet(linkNativeFeed); - } - /** * @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes. * @param size is the size of the fulfillment transaction in bytes. @@ -200,9 +181,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume * @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's * fulfillRandomWords function. * - * @param _wrapperNativePremiumPercentage is the premium ratio in percentage for wrapper requests paid in native. + * @param _coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for requests paid in native. * - * @param _wrapperLinkPremiumPercentage is the premium ratio in percentage for wrapper requests paid in link. + * @param _coordinatorLinkPremiumPercentage is the coordinator's premium ratio in percentage for requests paid in link. * * @param _keyHash to use for requesting randomness. * @param _maxNumWords is the max number of words that can be requested in a single wrapped VRF request @@ -221,8 +202,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume function setConfig( uint32 _wrapperGasOverhead, uint32 _coordinatorGasOverhead, - uint8 _wrapperNativePremiumPercentage, - uint8 _wrapperLinkPremiumPercentage, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, bytes32 _keyHash, uint8 _maxNumWords, uint32 _stalenessSeconds, @@ -233,17 +214,17 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume if (_fulfillmentFlatFeeLinkDiscountPPM > _fulfillmentFlatFeeNativePPM) { revert LinkDiscountTooHigh(_fulfillmentFlatFeeLinkDiscountPPM, _fulfillmentFlatFeeNativePPM); } - if (_wrapperNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(_wrapperNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); + if (_coordinatorNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(_coordinatorNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX); } - if (_wrapperLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { - revert InvalidPremiumPercentage(_wrapperLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); + if (_coordinatorLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) { + revert InvalidPremiumPercentage(_coordinatorLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX); } s_wrapperGasOverhead = _wrapperGasOverhead; s_coordinatorGasOverhead = _coordinatorGasOverhead; - s_wrapperNativePremiumPercentage = _wrapperNativePremiumPercentage; - s_wrapperLinkPremiumPercentage = _wrapperLinkPremiumPercentage; + s_coordinatorNativePremiumPercentage = _coordinatorNativePremiumPercentage; + s_coordinatorLinkPremiumPercentage = _coordinatorLinkPremiumPercentage; s_keyHash = _keyHash; s_maxNumWords = _maxNumWords; s_configured = true; @@ -257,8 +238,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume emit ConfigSet( _wrapperGasOverhead, _coordinatorGasOverhead, - _wrapperNativePremiumPercentage, - _wrapperLinkPremiumPercentage, + _coordinatorNativePremiumPercentage, + _coordinatorLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, @@ -324,8 +305,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume s_fulfillmentFlatFeeLinkDiscountPPM, s_wrapperGasOverhead, s_coordinatorGasOverhead, - s_wrapperNativePremiumPercentage, - s_wrapperLinkPremiumPercentage, + s_coordinatorNativePremiumPercentage, + s_coordinatorLinkPremiumPercentage, s_keyHash, s_maxNumWords ); @@ -390,8 +371,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied // coordinator cost * premium multiplier + flat fee - uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * (s_wrapperNativePremiumPercentage + 100)) / - 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM)); + uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * + (s_coordinatorNativePremiumPercentage + 100)) / 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM)); return wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei; } @@ -413,8 +394,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume // coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied // coordinator cost * premium multiplier + flat fee - uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * (s_wrapperLinkPremiumPercentage + 100)) / - 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM)); + uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * + (s_coordinatorLinkPremiumPercentage + 100)) / 100) + + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM)); // requestPrice is denominated in juels (link) // (1e18 juels/link) * wei / (wei/link) = juels @@ -596,10 +578,14 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume return address(i_link); } + function linkNativeFeed() external view override returns (address) { + return address(i_link_native_feed); + } + function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) { uint32 stalenessSeconds = s_stalenessSeconds; uint256 timestamp; - (, weiPerUnitLink, , timestamp, ) = s_linkNativeFeed.latestRoundData(); + (, weiPerUnitLink, , timestamp, ) = i_link_native_feed.latestRoundData(); // solhint-disable-next-line not-rely-on-time isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp; if (isFeedStale) { diff --git a/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol b/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol index c1ee4921459..93f6bf0ef11 100644 --- a/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol +++ b/contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol @@ -2,13 +2,12 @@ pragma solidity ^0.8.0; interface IVRFV2PlusWrapper { - event LinkNativeFeedSet(address linkNativeFeed); event FulfillmentTxSizeSet(uint32 size); event ConfigSet( uint32 wrapperGasOverhead, uint32 coordinatorGasOverhead, - uint8 wrapperNativePremiumPercentage, - uint8 wrapperLinkPremiumPercentage, + uint8 coordinatorNativePremiumPercentage, + uint8 coordinatorLinkPremiumPercentage, bytes32 keyHash, uint8 maxNumWords, uint32 stalenessSeconds, @@ -90,4 +89,5 @@ interface IVRFV2PlusWrapper { ) external payable returns (uint256 requestId); function link() external view returns (address); + function linkNativeFeed() external view returns (address); } diff --git a/contracts/src/v0.8/vrf/test/BaseTest.t.sol b/contracts/src/v0.8/vrf/test/BaseTest.t.sol new file mode 100644 index 00000000000..4da698d1740 --- /dev/null +++ b/contracts/src/v0.8/vrf/test/BaseTest.t.sol @@ -0,0 +1,17 @@ +pragma solidity ^0.8.0; + +import {Test} from "forge-std/Test.sol"; + +contract BaseTest is Test { + bool private s_baseTestInitialized; + address internal constant OWNER = 0x00007e64E1fB0C487F25dd6D3601ff6aF8d32e4e; + + function setUp() public virtual { + // BaseTest.setUp is often called multiple times from tests' setUp due to inheritance. + if (s_baseTestInitialized) return; + s_baseTestInitialized = true; + + // Set msg.sender to OWNER until changePrank or stopPrank is called + vm.startPrank(OWNER); + } +} diff --git a/contracts/test/v0.8/foundry/vrf/ChainSpecificUtil.t.sol b/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol similarity index 94% rename from contracts/test/v0.8/foundry/vrf/ChainSpecificUtil.t.sol rename to contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol index eaf76610054..efeb9027462 100644 --- a/contracts/test/v0.8/foundry/vrf/ChainSpecificUtil.t.sol +++ b/contracts/src/v0.8/vrf/test/ChainSpecificUtil.t.sol @@ -1,10 +1,11 @@ pragma solidity 0.8.6; -import "../BaseTest.t.sol"; -import {ChainSpecificUtil} from "../../../../src/v0.8/ChainSpecificUtil_v0_8_6.sol"; -import {ArbSys} from "../../../../src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; -import {ArbGasInfo} from "../../../../src/v0.8/vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; -import {OVM_GasPriceOracle} from "../../../../src/v0.8/vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; +import "./BaseTest.t.sol"; +import {ChainSpecificUtil} from "../../ChainSpecificUtil_v0_8_6.sol"; + +import {ArbSys} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol"; +import {ArbGasInfo} from "../../vendor/@arbitrum/nitro-contracts/src/precompiles/ArbGasInfo.sol"; +import {OVM_GasPriceOracle} from "../../vendor/@eth-optimism/contracts/v0.8.6/contracts/L2/predeploys/OVM_GasPriceOracle.sol"; contract ChainSpecificUtilTest is BaseTest { // ------------ Start Arbitrum Constants ------------ diff --git a/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol b/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol similarity index 96% rename from contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol rename to contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol index 4f79cb4f071..ec47f4815d9 100644 --- a/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol +++ b/contracts/src/v0.8/vrf/test/TrustedBlockhashStore.t.sol @@ -1,7 +1,7 @@ pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {TrustedBlockhashStore} from "../../../../src/v0.8/vrf/dev/TrustedBlockhashStore.sol"; +import "./BaseTest.t.sol"; +import {TrustedBlockhashStore} from "../dev/TrustedBlockhashStore.sol"; import {console} from "forge-std/console.sol"; contract TrustedBlockhashStoreTest is BaseTest { diff --git a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Mock.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol similarity index 96% rename from contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Mock.t.sol rename to contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol index 6378d40167b..1716118b765 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Mock.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Mock.t.sol @@ -1,11 +1,11 @@ pragma solidity 0.8.6; -import "../BaseTest.t.sol"; -import {VRF} from "../../../../src/v0.8/vrf/VRF.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import {VRFCoordinatorV2Mock} from "../../../../src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol"; -import {VRFConsumerV2} from "../../../../src/v0.8/vrf/testhelpers/VRFConsumerV2.sol"; +import "./BaseTest.t.sol"; +import {VRF} from "../VRF.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {VRFCoordinatorV2Mock} from "../mocks/VRFCoordinatorV2Mock.sol"; +import {VRFConsumerV2} from "../testhelpers/VRFConsumerV2.sol"; contract VRFCoordinatorV2MockTest is BaseTest { MockLinkToken internal s_linkToken; diff --git a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol similarity index 94% rename from contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol rename to contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol index 9b183db3ddc..31585656b37 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFCoordinatorV2Plus_Migration.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFCoordinatorV2Plus_Migration.t.sol @@ -1,14 +1,14 @@ pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {VRFCoordinatorV2Plus_V2Example} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; -import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol"; -import {VRFV2PlusConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import {VRFV2PlusMaliciousMigrator} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusMaliciousMigrator.sol"; +import "./BaseTest.t.sol"; +import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {VRFV2PlusMaliciousMigrator} from "../dev/testhelpers/VRFV2PlusMaliciousMigrator.sol"; contract VRFCoordinatorV2Plus_Migration is BaseTest { uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 LINK diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol similarity index 98% rename from contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol rename to contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol index 241a06c1359..b7c2c1f882e 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2Plus.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2Plus.t.sol @@ -1,19 +1,19 @@ pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {VRF} from "../../../../src/v0.8/vrf/VRF.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol"; -import {BlockhashStore} from "../../../../src/v0.8/vrf/dev/BlockhashStore.sol"; -import {VRFV2PlusConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusConsumerExample.sol"; -import {VRFV2PlusClient} from "../../../../src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; -import {VRFTypes} from "../../../../src/v0.8/vrf/VRFTypes.sol"; +import "./BaseTest.t.sol"; +import {VRF} from "../VRF.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {BlockhashStore} from "../dev/BlockhashStore.sol"; +import {VRFV2PlusConsumerExample} from "../dev/testhelpers/VRFV2PlusConsumerExample.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; +import {VRFTypes} from "../VRFTypes.sol"; import {console} from "forge-std/console.sol"; import {VmSafe} from "forge-std/Vm.sol"; -import {VRFV2PlusLoadTestWithMetrics} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; +import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; // for Math.ceilDiv /* diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol similarity index 98% rename from contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol rename to contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol index 763f72f9d92..4fbb44ea717 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2PlusSubscriptionAPI.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusSubscriptionAPI.t.sol @@ -1,11 +1,11 @@ pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFV2PlusLoadTestWithMetrics} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; -import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; +import "./BaseTest.t.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFV2PlusLoadTestWithMetrics} from "../dev/testhelpers/VRFV2PlusLoadTestWithMetrics.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; // for Strings.toString import {VmSafe} from "forge-std/Vm.sol"; diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol similarity index 82% rename from contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper.t.sol rename to contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol index b0ef92978c0..e40172717b2 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol @@ -1,31 +1,29 @@ +// SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {VRF} from "../../../../src/v0.8/vrf/VRF.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol"; -import {VRFV2PlusWrapperConsumerBase} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol"; -import {VRFV2PlusWrapperConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; -import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol"; -import {VRFConsumerBaseV2Plus} from "../../../../src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol"; -import {VRFV2PlusWrapper} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol"; -import {VRFV2PlusClient} from "../../../../src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; -import {console} from "forge-std/console.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; +import {VRFCoordinatorV2_5} from "../dev/VRFCoordinatorV2_5.sol"; +import {VRFConsumerBaseV2Plus} from "../dev/VRFConsumerBaseV2Plus.sol"; +import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; +import {VRFV2PlusClient} from "../dev/libraries/VRFV2PlusClient.sol"; contract VRFV2PlusWrapperTest is BaseTest { address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; - bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint32 wrapperGasOverhead = 10_000; - uint32 coordinatorGasOverhead = 20_000; - uint256 s_wrapperSubscriptionId; + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint32 private wrapperGasOverhead = 10_000; + uint32 private coordinatorGasOverhead = 20_000; + uint256 private s_wrapperSubscriptionId; - ExposedVRFCoordinatorV2_5 s_testCoordinator; - MockLinkToken s_linkToken; - MockV3Aggregator s_linkNativeFeed; - VRFV2PlusWrapper s_wrapper; - VRFV2PlusWrapperConsumerExample s_consumer; + ExposedVRFCoordinatorV2_5 private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper private s_wrapper; + VRFV2PlusWrapperConsumerExample private s_consumer; function setUp() public override { BaseTest.setUp(); @@ -53,6 +51,8 @@ contract VRFV2PlusWrapperTest is BaseTest { address(s_testCoordinator), uint256(s_wrapperSubscriptionId) ); + assertEq(address(s_linkToken), address(s_wrapper.link())); + assertEq(address(s_linkNativeFeed), address(s_wrapper.linkNativeFeed())); // Add wrapper as a consumer to the wrapper's subscription. s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper)); @@ -104,15 +104,15 @@ contract VRFV2PlusWrapperTest is BaseTest { , uint32 _wrapperGasOverhead, uint32 _coordinatorGasOverhead, - uint8 _wrapperNativePremiumPercentage, - uint8 _wrapperLinkPremiumPercentage, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, bytes32 _keyHash, uint8 _maxNumWords ) = s_wrapper.getConfig(); assertEq(_wrapperGasOverhead, wrapperGasOverhead); assertEq(_coordinatorGasOverhead, coordinatorGasOverhead); - assertEq(0, _wrapperNativePremiumPercentage); - assertEq(0, _wrapperLinkPremiumPercentage); + assertEq(0, _coordinatorNativePremiumPercentage); + assertEq(0, _coordinatorLinkPremiumPercentage); assertEq(vrfKeyHash, _keyHash); assertEq(10, _maxNumWords); } @@ -135,8 +135,8 @@ contract VRFV2PlusWrapperTest is BaseTest { event ConfigSet( uint32 wrapperGasOverhead, uint32 coordinatorGasOverhead, - uint8 wrapperNativePremiumPercentage, - uint8 wrapperLinkPremiumPercentage, + uint8 coordinatorNativePremiumPercentage, + uint8 coordinatorLinkPremiumPercentage, bytes32 keyHash, uint8 maxNumWords, uint32 stalenessSeconds, @@ -156,16 +156,16 @@ contract VRFV2PlusWrapperTest is BaseTest { // SubscriptionAPI events event SubscriptionConsumerAdded(uint256 indexed subId, address consumer); - function testVRFV2PlusWrapper_ZeroAddress() public { + function testVRFV2PlusWrapperZeroAddress() public { vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(0), address(0), uint256(0)); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(0), uint256(0)); } function testCreationOfANewVRFV2PlusWrapper() public { // second wrapper contract will simply add itself to the same subscription VRFV2PlusWrapper nextWrapper = new VRFV2PlusWrapper( address(s_linkToken), - address(0), + address(s_linkNativeFeed), address(s_testCoordinator), s_wrapperSubscriptionId ); @@ -174,27 +174,12 @@ contract VRFV2PlusWrapperTest is BaseTest { function testVRFV2PlusWrapperWithZeroSubscriptionId() public { vm.expectRevert(VRFV2PlusWrapper.SubscriptionIdMissing.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(0), address(s_testCoordinator), uint256(0)); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(0)); } function testVRFV2PlusWrapperWithInvalidSubscriptionId() public { vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector); - new VRFV2PlusWrapper(address(s_linkToken), address(0), address(s_testCoordinator), uint256(123456)); - } - - function testSetLinkAndLinkNativeFeed() public { - VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper( - address(s_linkToken), - address(0), - address(s_testCoordinator), - uint256(s_wrapperSubscriptionId) - ); - - // Set LINK/Native feed on wrapper. - vm.expectEmit(false, false, false, true, address(wrapper)); - emit LinkNativeFeedSet(address(s_linkNativeFeed)); - wrapper.setLinkNativeFeed(address(s_linkNativeFeed)); - assertEq(address(wrapper.s_linkNativeFeed()), address(s_linkNativeFeed)); + new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(123456)); } function testSetFulfillmentTxSize() public { @@ -205,7 +190,7 @@ contract VRFV2PlusWrapperTest is BaseTest { assertEq(s_wrapper.s_fulfillmentTxSizeBytes(), fulfillmentTxSize); } - function testSetCoordinator_ZeroAddress() public { + function testSetCoordinatorZeroAddress() public { vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector); s_wrapper.setCoordinator(address(0)); } @@ -283,7 +268,7 @@ contract VRFV2PlusWrapperTest is BaseTest { assertEq(address(s_wrapper).balance, 0); } - function testSetConfig_FulfillmentFlatFee_LinkDiscountTooHigh() public { + function testSetConfigFulfillmentFlatFee_LinkDiscountTooHigh() public { // Test that setting link discount flat fee higher than native flat fee reverts vm.expectRevert(abi.encodeWithSelector(VRFV2PlusWrapper.LinkDiscountTooHigh.selector, uint32(501), uint32(500))); s_wrapper.setConfig( @@ -300,7 +285,7 @@ contract VRFV2PlusWrapperTest is BaseTest { ); } - function testSetConfig_FulfillmentFlatFee_LinkDiscountEqualsNative() public { + function testSetConfigFulfillmentFlatFee_LinkDiscountEqualsNative() public { // Test that setting link discount flat fee equal to native flat fee does not revert s_wrapper.setConfig( wrapperGasOverhead, // wrapper gas overhead @@ -316,7 +301,7 @@ contract VRFV2PlusWrapperTest is BaseTest { ); } - function testSetConfig_NativePremiumPercentage_InvalidPremiumPercentage() public { + function testSetConfigNativePremiumPercentageInvalidPremiumPercentage() public { // Test that setting native premium percentage higher than 155 will revert vm.expectRevert( abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155)) @@ -335,7 +320,7 @@ contract VRFV2PlusWrapperTest is BaseTest { ); } - function testSetConfig_LinkPremiumPercentage_InvalidPremiumPercentage() public { + function testSetConfigLinkPremiumPercentageInvalidPremiumPercentage() public { // Test that setting LINK premium percentage higher than 155 will revert vm.expectRevert( abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155)) @@ -415,7 +400,7 @@ contract VRFV2PlusWrapperTest is BaseTest { assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); } - function testRequestRandomWordsLINKWrapper_FallbackWeiPerUnitLinkUsed() public { + function testRequestRandomWordsLINKWrapperFallbackWeiPerUnitLinkUsed() public { // Fund subscription. s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID())); s_linkToken.transfer(address(s_consumer), 10 ether); @@ -452,7 +437,7 @@ contract VRFV2PlusWrapperTest is BaseTest { s_consumer.makeRequest(callbackGasLimit, 0, 1); } - function testRequestRandomWordsInNative_NotConfigured() public { + function testRequestRandomWordsInNativeNotConfigured() public { VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper( address(s_linkToken), address(s_linkNativeFeed), @@ -464,7 +449,7 @@ contract VRFV2PlusWrapperTest is BaseTest { wrapper.requestRandomWordsInNative(500_000, 0, 1, ""); } - function testRequestRandomWordsInNative_Disabled() public { + function testRequestRandomWordsInNativeDisabled() public { s_wrapper.disable(); vm.expectRevert("wrapper is disabled"); diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper_Migration.t.sol b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol similarity index 89% rename from contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper_Migration.t.sol rename to contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol index 07f7a0e022d..deaef4ba84e 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper_Migration.t.sol +++ b/contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol @@ -1,34 +1,31 @@ +// SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import "../BaseTest.t.sol"; -import {VRF} from "../../../../src/v0.8/vrf/VRF.sol"; -import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; -import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; -import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; -import {VRFCoordinatorV2Plus_V2Example} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; -import {VRFV2PlusWrapperConsumerBase} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol"; -import {VRFV2PlusWrapperConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; -import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol"; -import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol"; -import {VRFV2PlusWrapper} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol"; -import {VRFV2PlusClient} from "../../../../src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol"; +import {BaseTest} from "./BaseTest.t.sol"; +import {MockLinkToken} from "../../mocks/MockLinkToken.sol"; +import {MockV3Aggregator} from "../../tests/MockV3Aggregator.sol"; +import {ExposedVRFCoordinatorV2_5} from "../dev/testhelpers/ExposedVRFCoordinatorV2_5.sol"; +import {VRFCoordinatorV2Plus_V2Example} from "../dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol"; +import {VRFV2PlusWrapperConsumerExample} from "../dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; +import {SubscriptionAPI} from "../dev/SubscriptionAPI.sol"; +import {VRFV2PlusWrapper} from "../dev/VRFV2PlusWrapper.sol"; contract VRFV2PlusWrapper_MigrationTest is BaseTest { address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B; uint256 internal constant DEFAULT_NATIVE_FUNDING = 7 ether; // 7 ETH uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 ETH - bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; - uint32 wrapperGasOverhead = 10_000; - uint32 coordinatorGasOverhead = 20_000; - uint256 s_wrapperSubscriptionId; + bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528"; + uint32 private wrapperGasOverhead = 10_000; + uint32 private coordinatorGasOverhead = 20_000; + uint256 private s_wrapperSubscriptionId; - ExposedVRFCoordinatorV2_5 s_testCoordinator; - MockLinkToken s_linkToken; - MockV3Aggregator s_linkNativeFeed; - VRFV2PlusWrapper s_wrapper; - VRFV2PlusWrapperConsumerExample s_consumer; + ExposedVRFCoordinatorV2_5 private s_testCoordinator; + MockLinkToken private s_linkToken; + MockV3Aggregator private s_linkNativeFeed; + VRFV2PlusWrapper private s_wrapper; + VRFV2PlusWrapperConsumerExample private s_consumer; - VRFCoordinatorV2Plus_V2Example s_newCoordinator; + VRFCoordinatorV2Plus_V2Example private s_newCoordinator; event CoordinatorRegistered(address coordinatorAddress); event MigrationCompleted(address newCoordinator, uint256 subId); @@ -121,15 +118,15 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest { , uint32 _wrapperGasOverhead, uint32 _coordinatorGasOverhead, - uint8 _wrapperNativePremiumPercentage, - uint8 _wrapperLinkPremiumPercentage, + uint8 _coordinatorNativePremiumPercentage, + uint8 _coordinatorLinkPremiumPercentage, bytes32 _keyHash, uint8 _maxNumWords ) = s_wrapper.getConfig(); assertEq(_wrapperGasOverhead, wrapperGasOverhead); assertEq(_coordinatorGasOverhead, coordinatorGasOverhead); - assertEq(0, _wrapperNativePremiumPercentage); - assertEq(0, _wrapperLinkPremiumPercentage); + assertEq(0, _coordinatorNativePremiumPercentage); + assertEq(0, _coordinatorLinkPremiumPercentage); assertEq(vrfKeyHash, _keyHash); assertEq(10, _maxNumWords); } diff --git a/contracts/test/v0.8/ChainlinkClient.test.ts b/contracts/test/v0.8/ChainlinkClient.test.ts index ae004fc32ac..f14fc43aaf5 100644 --- a/contracts/test/v0.8/ChainlinkClient.test.ts +++ b/contracts/test/v0.8/ChainlinkClient.test.ts @@ -27,7 +27,7 @@ before(async () => { roles.defaultAccount, ) emptyOracleFactory = await ethers.getContractFactory( - 'src/v0.6/tests/EmptyOracle.sol:EmptyOracle', + 'src/v0.8/operatorforwarder/dev/tests/testhelpers/EmptyOracle.sol:EmptyOracle', roles.defaultAccount, ) getterSetterFactory = await ethers.getContractFactory( @@ -35,7 +35,7 @@ before(async () => { roles.defaultAccount, ) operatorFactory = await ethers.getContractFactory( - 'src/v0.7/Operator.sol:Operator', + 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', roles.defaultAccount, ) linkTokenFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/dev/ArbitrumCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/ArbitrumCrossDomainForwarder.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ArbitrumCrossDomainForwarder.test.ts rename to contracts/test/v0.8/L2EP/ArbitrumCrossDomainForwarder.test.ts diff --git a/contracts/test/v0.8/dev/ArbitrumCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/ArbitrumCrossDomainGovernor.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ArbitrumCrossDomainGovernor.test.ts rename to contracts/test/v0.8/L2EP/ArbitrumCrossDomainGovernor.test.ts diff --git a/contracts/test/v0.8/dev/ArbitrumSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/ArbitrumSequencerUptimeFeed.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ArbitrumSequencerUptimeFeed.test.ts rename to contracts/test/v0.8/L2EP/ArbitrumSequencerUptimeFeed.test.ts diff --git a/contracts/test/v0.8/dev/ArbitrumValidator.test.ts b/contracts/test/v0.8/L2EP/ArbitrumValidator.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ArbitrumValidator.test.ts rename to contracts/test/v0.8/L2EP/ArbitrumValidator.test.ts diff --git a/contracts/test/v0.8/dev/OptimismCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/OptimismCrossDomainForwarder.test.ts similarity index 100% rename from contracts/test/v0.8/dev/OptimismCrossDomainForwarder.test.ts rename to contracts/test/v0.8/L2EP/OptimismCrossDomainForwarder.test.ts diff --git a/contracts/test/v0.8/dev/OptimismCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/OptimismCrossDomainGovernor.test.ts similarity index 100% rename from contracts/test/v0.8/dev/OptimismCrossDomainGovernor.test.ts rename to contracts/test/v0.8/L2EP/OptimismCrossDomainGovernor.test.ts diff --git a/contracts/test/v0.8/dev/OptimismSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/OptimismSequencerUptimeFeed.test.ts similarity index 100% rename from contracts/test/v0.8/dev/OptimismSequencerUptimeFeed.test.ts rename to contracts/test/v0.8/L2EP/OptimismSequencerUptimeFeed.test.ts diff --git a/contracts/test/v0.8/dev/OptimismValidator.test.ts b/contracts/test/v0.8/L2EP/OptimismValidator.test.ts similarity index 100% rename from contracts/test/v0.8/dev/OptimismValidator.test.ts rename to contracts/test/v0.8/L2EP/OptimismValidator.test.ts diff --git a/contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts b/contracts/test/v0.8/L2EP/ScrollCrossDomainForwarder.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ScrollCrossDomainForwarder.test.ts rename to contracts/test/v0.8/L2EP/ScrollCrossDomainForwarder.test.ts diff --git a/contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts b/contracts/test/v0.8/L2EP/ScrollCrossDomainGovernor.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ScrollCrossDomainGovernor.test.ts rename to contracts/test/v0.8/L2EP/ScrollCrossDomainGovernor.test.ts diff --git a/contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts b/contracts/test/v0.8/L2EP/ScrollSequencerUptimeFeed.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ScrollSequencerUptimeFeed.test.ts rename to contracts/test/v0.8/L2EP/ScrollSequencerUptimeFeed.test.ts diff --git a/contracts/test/v0.8/dev/ScrollValidator.test.ts b/contracts/test/v0.8/L2EP/ScrollValidator.test.ts similarity index 100% rename from contracts/test/v0.8/dev/ScrollValidator.test.ts rename to contracts/test/v0.8/L2EP/ScrollValidator.test.ts diff --git a/contracts/test/v0.8/VRFD20.test.ts b/contracts/test/v0.8/VRFD20.test.ts deleted file mode 100644 index 8369d1b4e24..00000000000 --- a/contracts/test/v0.8/VRFD20.test.ts +++ /dev/null @@ -1,303 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { - BigNumber, - constants, - Contract, - ContractFactory, - ContractTransaction, -} from 'ethers' -import { getUsers, Personas, Roles } from '../test-helpers/setup' -import { - evmWordToAddress, - getLog, - publicAbi, - toBytes32String, - toWei, - numToBytes32, - getLogs, -} from '../test-helpers/helpers' - -let roles: Roles -let personas: Personas -let linkTokenFactory: ContractFactory -let vrfCoordinatorMockFactory: ContractFactory -let vrfD20Factory: ContractFactory - -before(async () => { - const users = await getUsers() - - roles = users.roles - personas = users.personas - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - roles.defaultAccount, - ) - vrfCoordinatorMockFactory = await ethers.getContractFactory( - 'src/v0.8/vrf/mocks/VRFCoordinatorMock.sol:VRFCoordinatorMock', - roles.defaultAccount, - ) - vrfD20Factory = await ethers.getContractFactory( - 'src/v0.6/examples/VRFD20.sol:VRFD20', - roles.defaultAccount, - ) -}) - -describe('VRFD20', () => { - const deposit = toWei('1') - const fee = toWei('0.1') - const keyHash = toBytes32String('keyHash') - - let link: Contract - let vrfCoordinator: Contract - let vrfD20: Contract - - beforeEach(async () => { - link = await linkTokenFactory.connect(roles.defaultAccount).deploy() - vrfCoordinator = await vrfCoordinatorMockFactory - .connect(roles.defaultAccount) - .deploy(link.address) - vrfD20 = await vrfD20Factory - .connect(roles.defaultAccount) - .deploy(vrfCoordinator.address, link.address, keyHash, fee) - await link.transfer(vrfD20.address, deposit) - }) - - it('has a limited public interface [ @skip-coverage ]', () => { - publicAbi(vrfD20, [ - // Owned - 'acceptOwnership', - 'owner', - 'transferOwnership', - //VRFConsumerBase - 'rawFulfillRandomness', - // VRFD20 - 'rollDice', - 'house', - 'withdrawLINK', - 'keyHash', - 'fee', - 'setKeyHash', - 'setFee', - ]) - }) - - describe('#withdrawLINK', () => { - describe('failure', () => { - it('reverts when called by a non-owner', async () => { - await expect( - vrfD20 - .connect(roles.stranger) - .withdrawLINK(await roles.stranger.getAddress(), deposit), - ).to.be.revertedWith('Only callable by owner') - }) - - it('reverts when not enough LINK in the contract', async () => { - const withdrawAmount = deposit.mul(2) - await expect( - vrfD20 - .connect(roles.defaultAccount) - .withdrawLINK( - await roles.defaultAccount.getAddress(), - withdrawAmount, - ), - ).to.be.reverted - }) - }) - - describe('success', () => { - it('withdraws LINK', async () => { - const startingAmount = await link.balanceOf( - await roles.defaultAccount.getAddress(), - ) - const expectedAmount = BigNumber.from(startingAmount).add(deposit) - await vrfD20 - .connect(roles.defaultAccount) - .withdrawLINK(await roles.defaultAccount.getAddress(), deposit) - const actualAmount = await link.balanceOf( - await roles.defaultAccount.getAddress(), - ) - assert.equal(actualAmount.toString(), expectedAmount.toString()) - }) - }) - }) - - describe('#setKeyHash', () => { - const newHash = toBytes32String('newhash') - - describe('failure', () => { - it('reverts when called by a non-owner', async () => { - await expect( - vrfD20.connect(roles.stranger).setKeyHash(newHash), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('success', () => { - it('sets the key hash', async () => { - await vrfD20.setKeyHash(newHash) - const actualHash = await vrfD20.keyHash() - assert.equal(actualHash, newHash) - }) - }) - }) - - describe('#setFee', () => { - const newFee = 1234 - - describe('failure', () => { - it('reverts when called by a non-owner', async () => { - await expect( - vrfD20.connect(roles.stranger).setFee(newFee), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('success', () => { - it('sets the fee', async () => { - await vrfD20.setFee(newFee) - const actualFee = await vrfD20.fee() - assert.equal(actualFee.toString(), newFee.toString()) - }) - }) - }) - - describe('#house', () => { - describe('failure', () => { - it('reverts when dice not rolled', async () => { - await expect( - vrfD20.house(await personas.Nancy.getAddress()), - ).to.be.revertedWith('Dice not rolled') - }) - - it('reverts when dice roll is in progress', async () => { - await vrfD20.rollDice(await personas.Nancy.getAddress()) - await expect( - vrfD20.house(await personas.Nancy.getAddress()), - ).to.be.revertedWith('Roll in progress') - }) - }) - - describe('success', () => { - it('returns the correct house', async () => { - const randomness = 98765 - const expectedHouse = 'Martell' - const tx = await vrfD20.rollDice(await personas.Nancy.getAddress()) - const log = await getLog(tx, 3) - const eventRequestId = log?.topics?.[1] - await vrfCoordinator.callBackWithRandomness( - eventRequestId, - randomness, - vrfD20.address, - ) - const response = await vrfD20.house(await personas.Nancy.getAddress()) - assert.equal(response.toString(), expectedHouse) - }) - }) - }) - - describe('#rollDice', () => { - describe('success', () => { - let tx: ContractTransaction - beforeEach(async () => { - tx = await vrfD20.rollDice(await personas.Nancy.getAddress()) - }) - - it('emits a RandomnessRequest event from the VRFCoordinator', async () => { - const log = await getLog(tx, 2) - const topics = log?.topics - assert.equal(evmWordToAddress(topics?.[1]), vrfD20.address) - assert.equal(topics?.[2], keyHash) - assert.equal(topics?.[3], constants.HashZero) - }) - }) - - describe('failure', () => { - it('reverts when LINK balance is zero', async () => { - const vrfD202 = await vrfD20Factory - .connect(roles.defaultAccount) - .deploy(vrfCoordinator.address, link.address, keyHash, fee) - await expect( - vrfD202.rollDice(await personas.Nancy.getAddress()), - ).to.be.revertedWith('Not enough LINK to pay fee') - }) - - it('reverts when called by a non-owner', async () => { - await expect( - vrfD20 - .connect(roles.stranger) - .rollDice(await personas.Nancy.getAddress()), - ).to.be.revertedWith('Only callable by owner') - }) - - it('reverts when the roller rolls more than once', async () => { - await vrfD20.rollDice(await personas.Nancy.getAddress()) - await expect( - vrfD20.rollDice(await personas.Nancy.getAddress()), - ).to.be.revertedWith('Already rolled') - }) - }) - }) - - describe('#fulfillRandomness', () => { - const randomness = 98765 - const expectedModResult = (randomness % 20) + 1 - const expectedHouse = 'Martell' - let eventRequestId: string - beforeEach(async () => { - const tx = await vrfD20.rollDice(await personas.Nancy.getAddress()) - const log = await getLog(tx, 3) - eventRequestId = log?.topics?.[1] - }) - - describe('success', () => { - let tx: ContractTransaction - beforeEach(async () => { - tx = await vrfCoordinator.callBackWithRandomness( - eventRequestId, - randomness, - vrfD20.address, - ) - }) - - it('emits a DiceLanded event', async () => { - const log = await getLog(tx, 0) - assert.equal(log?.topics[1], eventRequestId) - assert.equal(log?.topics[2], numToBytes32(expectedModResult)) - }) - - it('sets the correct dice roll result', async () => { - const response = await vrfD20.house(await personas.Nancy.getAddress()) - assert.equal(response.toString(), expectedHouse) - }) - - it('allows someone else to roll', async () => { - const secondRandomness = 55555 - tx = await vrfD20.rollDice(await personas.Ned.getAddress()) - const log = await getLog(tx, 3) - eventRequestId = log?.topics?.[1] - tx = await vrfCoordinator.callBackWithRandomness( - eventRequestId, - secondRandomness, - vrfD20.address, - ) - }) - }) - - describe('failure', () => { - it('does not fulfill when fulfilled by the wrong VRFcoordinator', async () => { - const vrfCoordinator2 = await vrfCoordinatorMockFactory - .connect(roles.defaultAccount) - .deploy(link.address) - - const tx = await vrfCoordinator2.callBackWithRandomness( - eventRequestId, - randomness, - vrfD20.address, - ) - const logs = await getLogs(tx) - assert.equal(logs.length, 0) - }) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts index 8b34facc9ce..9ec883cc401 100644 --- a/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts +++ b/contracts/test/v0.8/automation/AutomationRegistry2_3.test.ts @@ -4636,7 +4636,7 @@ describe('AutomationRegistry2_3', () => { describe('#withdrawOwnerFunds', () => { it('can only be called by finance admin', async () => { await evmRevert( - registry.connect(keeper1).withdrawLinkFees(zeroAddress, 1), + registry.connect(keeper1).withdrawLink(zeroAddress, 1), 'OnlyFinanceAdmin()', ) }) @@ -4693,7 +4693,7 @@ describe('AutomationRegistry2_3', () => { // Now withdraw await registry .connect(financeAdmin) - .withdrawLinkFees(await owner.getAddress(), ownerRegistryBalance) + .withdrawLink(await owner.getAddress(), ownerRegistryBalance) ownerRegistryBalance = await registry.linkAvailableForPayment() const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) diff --git a/contracts/test/cross-version/KeeperCompatible.test.ts b/contracts/test/v0.8/automation/KeeperCompatible.test.ts similarity index 89% rename from contracts/test/cross-version/KeeperCompatible.test.ts rename to contracts/test/v0.8/automation/KeeperCompatible.test.ts index 968ce65f208..13d1d0deff5 100644 --- a/contracts/test/cross-version/KeeperCompatible.test.ts +++ b/contracts/test/v0.8/automation/KeeperCompatible.test.ts @@ -1,10 +1,10 @@ import { ethers } from 'hardhat' import { Contract } from 'ethers' import { expect } from 'chai' -import { publicAbi } from '../test-helpers/helpers' +import { publicAbi } from '../../test-helpers/helpers' describe('KeeperCompatible', () => { - for (let version = 6; version <= 8; version++) { + for (let version = 8; version <= 8; version++) { describe(`version v0.${version}`, () => { let contract: Contract diff --git a/contracts/test/v0.8/KeeperRegistrar.test.ts b/contracts/test/v0.8/automation/KeeperRegistrar.test.ts similarity index 96% rename from contracts/test/v0.8/KeeperRegistrar.test.ts rename to contracts/test/v0.8/automation/KeeperRegistrar.test.ts index bde871cc5c4..717bccae3a4 100644 --- a/contracts/test/v0.8/KeeperRegistrar.test.ts +++ b/contracts/test/v0.8/automation/KeeperRegistrar.test.ts @@ -1,21 +1,21 @@ import { ethers } from 'hardhat' import { assert, expect } from 'chai' -import { evmRevert } from '../test-helpers/matchers' -import { getUsers, Personas } from '../test-helpers/setup' +import { evmRevert } from '../../test-helpers/matchers' +import { getUsers, Personas } from '../../test-helpers/setup' import { BigNumber, Signer } from 'ethers' -import { LinkToken__factory as LinkTokenFactory } from '../../typechain/factories/LinkToken__factory' - -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../typechain/factories/UpkeepMock__factory' -import { KeeperRegistry1_2 as KeeperRegistry } from '../../typechain/KeeperRegistry1_2' -import { KeeperRegistry1_2__factory as KeeperRegistryFactory } from '../../typechain/factories/KeeperRegistry1_2__factory' -import { KeeperRegistrar } from '../../typechain/KeeperRegistrar' -import { KeeperRegistrar__factory as KeeperRegistrarFactory } from '../../typechain/factories/KeeperRegistrar__factory' - -import { MockV3Aggregator } from '../../typechain/MockV3Aggregator' -import { LinkToken } from '../../typechain/LinkToken' -import { UpkeepMock } from '../../typechain/UpkeepMock' -import { toWei } from '../test-helpers/helpers' +import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' + +import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' +import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' +import { KeeperRegistry1_2 as KeeperRegistry } from '../../../typechain/KeeperRegistry1_2' +import { KeeperRegistry1_2__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry1_2__factory' +import { KeeperRegistrar } from '../../../typechain/KeeperRegistrar' +import { KeeperRegistrar__factory as KeeperRegistrarFactory } from '../../../typechain/factories/KeeperRegistrar__factory' + +import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' +import { LinkToken } from '../../../typechain/LinkToken' +import { UpkeepMock } from '../../../typechain/UpkeepMock' +import { toWei } from '../../test-helpers/helpers' let linkTokenFactory: LinkTokenFactory let mockV3AggregatorFactory: MockV3AggregatorFactory diff --git a/contracts/test/v0.8/automation/KeeperRegistrar2_0.test.ts b/contracts/test/v0.8/automation/KeeperRegistrar2_0.test.ts deleted file mode 100644 index 9cb17e1af1e..00000000000 --- a/contracts/test/v0.8/automation/KeeperRegistrar2_0.test.ts +++ /dev/null @@ -1,937 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { evmRevert } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { BigNumber, Signer } from 'ethers' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' - -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { KeeperRegistry2_0 as KeeperRegistry } from '../../../typechain/KeeperRegistry2_0' -import { KeeperRegistryLogic20 as KeeperRegistryLogic } from '../../../typechain/KeeperRegistryLogic20' -import { KeeperRegistrar20 as KeeperRegistrar } from '../../../typechain/KeeperRegistrar20' -import { KeeperRegistry2_0__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry2_0__factory' -import { KeeperRegistryLogic2_0__factory as KeeperRegistryLogicFactory } from '../../../typechain/factories/KeeperRegistryLogic2_0__factory' -import { KeeperRegistrar2_0__factory as KeeperRegistrarFactory } from '../../../typechain/factories/KeeperRegistrar2_0__factory' - -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { LinkToken } from '../../../typechain/LinkToken' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { toWei } from '../../test-helpers/helpers' - -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory: KeeperRegistryFactory -let keeperRegistryLogicFactory: KeeperRegistryLogicFactory -let keeperRegistrar: KeeperRegistrarFactory -let upkeepMockFactory: UpkeepMockFactory - -let personas: Personas - -before(async () => { - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - // @ts-ignore bug in autogen file - keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry2_0') - // @ts-ignore bug in autogen file - keeperRegistryLogicFactory = await ethers.getContractFactory( - 'KeeperRegistryLogic2_0', - ) - // @ts-ignore bug in autogen file - keeperRegistrar = await ethers.getContractFactory('KeeperRegistrar2_0') - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') -}) - -const errorMsgs = { - onlyOwner: 'revert Only callable by owner', - onlyAdmin: 'OnlyAdminOrOwner()', - hashPayload: 'HashMismatch()', - requestNotFound: 'RequestNotFound()', -} - -describe('KeeperRegistrar2_0', () => { - const upkeepName = 'SampleUpkeep' - - const linkEth = BigNumber.from(300000000) - const gasWei = BigNumber.from(100) - const executeGas = BigNumber.from(100000) - const paymentPremiumPPB = BigNumber.from(250000000) - const flatFeeMicroLink = BigNumber.from(0) - const maxAllowedAutoApprove = 5 - const offchainConfig = '0x01234567' - - const emptyBytes = '0x00' - const stalenessSeconds = BigNumber.from(43820) - const gasCeilingMultiplier = BigNumber.from(1) - const checkGasLimit = BigNumber.from(20000000) - const fallbackGasPrice = BigNumber.from(200) - const fallbackLinkPrice = BigNumber.from(200000000) - const maxCheckDataSize = BigNumber.from(10000) - const maxPerformDataSize = BigNumber.from(10000) - const maxPerformGas = BigNumber.from(5000000) - const minUpkeepSpend = BigNumber.from('1000000000000000000') - const amount = BigNumber.from('5000000000000000000') - const amount1 = BigNumber.from('6000000000000000000') - const transcoder = ethers.constants.AddressZero - - // Enum values are not auto exported in ABI so have to manually declare - const autoApproveType_DISABLED = 0 - const autoApproveType_ENABLED_SENDER_ALLOWLIST = 1 - const autoApproveType_ENABLED_ALL = 2 - - let owner: Signer - let admin: Signer - let someAddress: Signer - let registrarOwner: Signer - let stranger: Signer - let requestSender: Signer - - let linkToken: LinkToken - let linkEthFeed: MockV3Aggregator - let gasPriceFeed: MockV3Aggregator - let registry: KeeperRegistry - let registryLogic: KeeperRegistryLogic - let mock: UpkeepMock - let registrar: KeeperRegistrar - - beforeEach(async () => { - owner = personas.Default - admin = personas.Neil - someAddress = personas.Ned - registrarOwner = personas.Nelly - stranger = personas.Nancy - requestSender = personas.Norbert - - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy(0, linkToken.address, linkEthFeed.address, gasPriceFeed.address) - - registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - - mock = await upkeepMockFactory.deploy() - - registrar = await keeperRegistrar - .connect(registrarOwner) - .deploy( - linkToken.address, - autoApproveType_DISABLED, - BigNumber.from('0'), - registry.address, - minUpkeepSpend, - ) - - await linkToken - .connect(owner) - .transfer(await requestSender.getAddress(), toWei('1000')) - - const keepers = [ - await personas.Carol.getAddress(), - await personas.Nancy.getAddress(), - await personas.Ned.getAddress(), - await personas.Neil.getAddress(), - ] - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder, - registrar: registrar.address, - } - const onchainConfig = ethers.utils.defaultAbiCoder.encode( - [ - 'tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds\ - ,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,\ - uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,\ - address registrar)', - ], - [config], - ) - await registry - .connect(owner) - .setConfig(keepers, keepers, 1, onchainConfig, 1, '0x') - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registrar.typeAndVersion() - assert.equal(typeAndVersion, 'KeeperRegistrar 2.0.0') - }) - }) - - describe('#register', () => { - it('reverts if not called by the LINK token', async () => { - await evmRevert( - registrar - .connect(someAddress) - .register( - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ), - 'OnlyLink()', - ) - }) - - it('reverts if the amount passed in data mismatches actual amount sent', async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount1, - await requestSender.getAddress(), - ], - ) - - await evmRevert( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - 'AmountMismatch()', - ) - }) - - it('reverts if the sender passed in data mismatches actual sender', async () => { - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await admin.getAddress(), // Should have been requestSender.getAddress() - ], - ) - await evmRevert( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - 'SenderMismatch()', - ) - }) - - it('reverts if the admin address is 0x0000...', async () => { - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - '0x0000000000000000000000000000000000000000', - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - - await evmRevert( - linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes), - 'RegistrationRequestFailed()', - ) - }) - - it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { - //set auto approve ON with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve ON - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - - const [id] = await registry.getActiveUpkeepIDs(0, 1) - - //confirm if a new upkeep has been registered and the details are the same as the one just registered - const newupkeep = await registry.getUpkeep(id) - assert.equal(newupkeep.target, mock.address) - assert.equal(newupkeep.admin, await admin.getAddress()) - assert.equal(newupkeep.checkData, emptyBytes) - assert.equal(newupkeep.balance.toString(), amount.toString()) - assert.equal(newupkeep.executeGas, executeGas.toNumber()) - assert.equal(newupkeep.offchainConfig, offchainConfig) - - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('Auto Approve OFF - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { - //get upkeep count before attempting registration - const beforeCount = (await registry.getState()).state.numUpkeeps - - //set auto approve OFF, threshold limits dont matter in this case - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - - //get upkeep count after attempting registration - const afterCount = (await registry.getState()).state.numUpkeeps - //confirm that a new upkeep has NOT been registered and upkeep count is still the same - assert.deepEqual(beforeCount, afterCount) - - //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).not.to.emit(registrar, 'RegistrationApproved') - - const hash = receipt.logs[2].topics[1] - const pendingRequest = await registrar.getPendingRequest(hash) - assert.equal(await admin.getAddress(), pendingRequest[0]) - assert.ok(amount.eq(pendingRequest[1])) - }) - - it('Auto Approve ON - Throttle max approvals - does not register an upkeep on KeeperRegistry beyond the max limit, emits only RegistrationRequested event after limit is hit', async () => { - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 0) - - //set auto approve on, with max 1 allowed - await registrar.connect(registrarOwner).setRegistrationConfig( - autoApproveType_ENABLED_ALL, - 1, // maxAllowedAutoApprove - registry.address, - minUpkeepSpend, - ) - - //register within threshold, new upkeep should be registered - let abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // 0 -> 1 - - //try registering another one, new upkeep should not be registered - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 1, // make unique hash - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // Still 1 - - // Now set new max limit to 2. One more upkeep should get auto approved - await registrar.connect(registrarOwner).setRegistrationConfig( - autoApproveType_ENABLED_ALL, - 2, // maxAllowedAutoApprove - registry.address, - minUpkeepSpend, - ) - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 2, // make unique hash - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 2) // 1 -> 2 - - // One more upkeep should not get registered - abiEncodedBytes = registrar.interface.encodeFunctionData('register', [ - upkeepName, - emptyBytes, - mock.address, - executeGas.toNumber() + 3, // make unique hash - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ]) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 2) // Still 2 - }) - - it('Auto Approve Sender Allowlist - sender in allowlist - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { - const senderAddress = await requestSender.getAddress() - - //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_SENDER_ALLOWLIST, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - // Add sender to allowlist - await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, true) - - //register with auto approve ON - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - - const [id] = await registry.getActiveUpkeepIDs(0, 1) - - //confirm if a new upkeep has been registered and the details are the same as the one just registered - const newupkeep = await registry.getUpkeep(id) - assert.equal(newupkeep.target, mock.address) - assert.equal(newupkeep.admin, await admin.getAddress()) - assert.equal(newupkeep.checkData, emptyBytes) - assert.equal(newupkeep.balance.toString(), amount.toString()) - assert.equal(newupkeep.executeGas, executeGas.toNumber()) - - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('Auto Approve Sender Allowlist - sender NOT in allowlist - does not registers an upkeep on KeeperRegistry, emits only RegistrationRequested event', async () => { - const beforeCount = (await registry.getState()).state.numUpkeeps - const senderAddress = await requestSender.getAddress() - - //set auto approve to ENABLED_SENDER_ALLOWLIST type with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_SENDER_ALLOWLIST, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - // Explicitly remove sender from allowlist - await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, false) - - //register. auto approve shouldn't happen - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - - //get upkeep count after attempting registration - const afterCount = (await registry.getState()).state.numUpkeeps - //confirm that a new upkeep has NOT been registered and upkeep count is still the same - assert.deepEqual(beforeCount, afterCount) - - //confirm that only RegistrationRequested event is emitted and RegistrationApproved event is not - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).not.to.emit(registrar, 'RegistrationApproved') - - const hash = receipt.logs[2].topics[1] - const pendingRequest = await registrar.getPendingRequest(hash) - assert.equal(await admin.getAddress(), pendingRequest[0]) - assert.ok(amount.eq(pendingRequest[1])) - }) - }) - - describe('#registerUpkeep', () => { - it('reverts with empty message if amount sent is not available in LINK allowance', async () => { - await evmRevert( - registrar.connect(someAddress).registerUpkeep({ - name: upkeepName, - upkeepContract: mock.address, - gasLimit: executeGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - offchainConfig: emptyBytes, - amount, - encryptedEmail: emptyBytes, - }), - '', - ) - }) - - it('reverts if the amount passed in data is less than configured minimum', async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - // amt is one order of magnitude less than minUpkeepSpend - const amt = BigNumber.from('100000000000000000') - - await evmRevert( - registrar.connect(someAddress).registerUpkeep({ - name: upkeepName, - upkeepContract: mock.address, - gasLimit: executeGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - offchainConfig: emptyBytes, - amount: amt, - encryptedEmail: emptyBytes, - }), - 'InsufficientPayment()', - ) - }) - - it('Auto Approve ON - registers an upkeep on KeeperRegistry instantly and emits both RegistrationRequested and RegistrationApproved events', async () => { - //set auto approve ON with high threshold limits - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_ENABLED_ALL, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - await linkToken.connect(requestSender).approve(registrar.address, amount) - - const tx = await registrar.connect(requestSender).registerUpkeep({ - name: upkeepName, - upkeepContract: mock.address, - gasLimit: executeGas, - adminAddress: await admin.getAddress(), - checkData: emptyBytes, - offchainConfig, - amount, - encryptedEmail: emptyBytes, - }) - assert.equal((await registry.getState()).state.numUpkeeps.toNumber(), 1) // 0 -> 1 - - //confirm if a new upkeep has been registered and the details are the same as the one just registered - const [id] = await registry.getActiveUpkeepIDs(0, 1) - const newupkeep = await registry.getUpkeep(id) - assert.equal(newupkeep.target, mock.address) - assert.equal(newupkeep.admin, await admin.getAddress()) - assert.equal(newupkeep.checkData, emptyBytes) - assert.equal(newupkeep.balance.toString(), amount.toString()) - assert.equal(newupkeep.executeGas, executeGas.toNumber()) - assert.equal(newupkeep.offchainConfig, offchainConfig) - - await expect(tx).to.emit(registrar, 'RegistrationRequested') - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - }) - - describe('#setAutoApproveAllowedSender', () => { - it('reverts if not called by the owner', async () => { - const tx = registrar - .connect(stranger) - .setAutoApproveAllowedSender(await admin.getAddress(), false) - await evmRevert(tx, 'Only callable by owner') - }) - - it('sets the allowed status correctly and emits log', async () => { - const senderAddress = await stranger.getAddress() - let tx = await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, true) - await expect(tx) - .to.emit(registrar, 'AutoApproveAllowedSenderSet') - .withArgs(senderAddress, true) - - let senderAllowedStatus = await registrar - .connect(owner) - .getAutoApproveAllowedSender(senderAddress) - assert.isTrue(senderAllowedStatus) - - tx = await registrar - .connect(registrarOwner) - .setAutoApproveAllowedSender(senderAddress, false) - await expect(tx) - .to.emit(registrar, 'AutoApproveAllowedSenderSet') - .withArgs(senderAddress, false) - - senderAllowedStatus = await registrar - .connect(owner) - .getAutoApproveAllowedSender(senderAddress) - assert.isFalse(senderAllowedStatus) - }) - }) - - describe('#approve', () => { - let hash: string - - beforeEach(async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] - }) - - it('reverts if not called by the owner', async () => { - const tx = registrar - .connect(stranger) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - hash, - ) - await evmRevert(tx, 'Only callable by owner') - }) - - it('reverts if the hash does not exist', async () => { - const tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) - await evmRevert(tx, errorMsgs.requestNotFound) - }) - - it('reverts if any member of the payload changes', async () => { - let tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - ethers.Wallet.createRandom().address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - hash, - ) - await evmRevert(tx, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - 10000, - await admin.getAddress(), - emptyBytes, - emptyBytes, - hash, - ) - await evmRevert(tx, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - ethers.Wallet.createRandom().address, - emptyBytes, - emptyBytes, - hash, - ) - await evmRevert(tx, errorMsgs.hashPayload) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - '0x1234', - emptyBytes, - hash, - ) - await evmRevert(tx, errorMsgs.hashPayload) - }) - - it('approves an existing registration request', async () => { - const tx = await registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - hash, - ) - await expect(tx).to.emit(registrar, 'RegistrationApproved') - }) - - it('deletes the request afterwards / reverts if the request DNE', async () => { - await registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - hash, - ) - const tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - hash, - ) - await evmRevert(tx, errorMsgs.requestNotFound) - }) - }) - - describe('#cancel', () => { - let hash: string - - beforeEach(async () => { - await registrar - .connect(registrarOwner) - .setRegistrationConfig( - autoApproveType_DISABLED, - maxAllowedAutoApprove, - registry.address, - minUpkeepSpend, - ) - - //register with auto approve OFF - const abiEncodedBytes = registrar.interface.encodeFunctionData( - 'register', - [ - upkeepName, - emptyBytes, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - offchainConfig, - amount, - await requestSender.getAddress(), - ], - ) - const tx = await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - const receipt = await tx.wait() - hash = receipt.logs[2].topics[1] - // submit duplicate request (increase balance) - await linkToken - .connect(requestSender) - .transferAndCall(registrar.address, amount, abiEncodedBytes) - }) - - it('reverts if not called by the admin / owner', async () => { - const tx = registrar.connect(stranger).cancel(hash) - await evmRevert(tx, errorMsgs.onlyAdmin) - }) - - it('reverts if the hash does not exist', async () => { - const tx = registrar - .connect(registrarOwner) - .cancel( - '0x000000000000000000000000322813fd9a801c5507c9de605d63cea4f2ce6c44', - ) - await evmRevert(tx, errorMsgs.requestNotFound) - }) - - it('refunds the total request balance to the admin address if owner cancels', async () => { - const before = await linkToken.balanceOf(await admin.getAddress()) - const tx = await registrar.connect(registrarOwner).cancel(hash) - const after = await linkToken.balanceOf(await admin.getAddress()) - assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2)))) - await expect(tx).to.emit(registrar, 'RegistrationRejected') - }) - - it('refunds the total request balance to the admin address if admin cancels', async () => { - const before = await linkToken.balanceOf(await admin.getAddress()) - const tx = await registrar.connect(admin).cancel(hash) - const after = await linkToken.balanceOf(await admin.getAddress()) - assert.isTrue(after.sub(before).eq(amount.mul(BigNumber.from(2)))) - await expect(tx).to.emit(registrar, 'RegistrationRejected') - }) - - it('deletes the request hash', async () => { - await registrar.connect(registrarOwner).cancel(hash) - let tx = registrar.connect(registrarOwner).cancel(hash) - await evmRevert(tx, errorMsgs.requestNotFound) - tx = registrar - .connect(registrarOwner) - .approve( - upkeepName, - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - hash, - ) - await evmRevert(tx, errorMsgs.requestNotFound) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperRegistry1_2.test.ts b/contracts/test/v0.8/automation/KeeperRegistry1_2.test.ts deleted file mode 100644 index 2fe7c119366..00000000000 --- a/contracts/test/v0.8/automation/KeeperRegistry1_2.test.ts +++ /dev/null @@ -1,2228 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { evmRevert } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { BigNumber, BigNumberish, Signer } from 'ethers' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { UpkeepReverter__factory as UpkeepReverterFactory } from '../../../typechain/factories/UpkeepReverter__factory' -import { UpkeepAutoFunder__factory as UpkeepAutoFunderFactory } from '../../../typechain/factories/UpkeepAutoFunder__factory' -import { UpkeepTranscoder__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder__factory' -import { KeeperRegistry1_2__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry1_2__factory' -import { KeeperRegistry1_2 as KeeperRegistry } from '../../../typechain/KeeperRegistry1_2' -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { LinkToken } from '../../../typechain/LinkToken' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' -import { toWei } from '../../test-helpers/helpers' - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** REGISTRY v1.2 IS FROZEN ************************************/ - -// All tests are disabled for this contract, as we expect it to never change in the future. -// Instead, we test that the bytecode for the contract has not changed. -// If this test ever fails, you should remove it and then re-run the original test suite. - -const BYTECODE = KeeperRegistryFactory.bytecode -const BYTECODE_CHECKSUM = - '0x4a23953416a64a0fa4c943954d9a92059f862257440f2cbcf5f238314b89f416' - -describe('KeeperRegistry1_2 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal(ethers.utils.id(BYTECODE), BYTECODE_CHECKSUM) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -async function getUpkeepID(tx: any) { - const receipt = await tx.wait() - return receipt.events[0].args.id -} - -function randomAddress() { - return ethers.Wallet.createRandom().address -} - -// ----------------------------------------------------------------------------------------------- -// DEV: these *should* match the perform/check gas overhead values in the contract and on the node -const PERFORM_GAS_OVERHEAD = BigNumber.from(160000) -const CHECK_GAS_OVERHEAD = BigNumber.from(170000) -// ----------------------------------------------------------------------------------------------- - -// Smart contract factories -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory: KeeperRegistryFactory -let upkeepMockFactory: UpkeepMockFactory -let upkeepReverterFactory: UpkeepReverterFactory -let upkeepAutoFunderFactory: UpkeepAutoFunderFactory -let upkeepTranscoderFactory: UpkeepTranscoderFactory -let personas: Personas - -before(async () => { - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - // need full path because there are two contracts with name MockV3Aggregator - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - // @ts-ignore bug in autogen file - keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry1_2') - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - upkeepReverterFactory = await ethers.getContractFactory('UpkeepReverter') - upkeepAutoFunderFactory = await ethers.getContractFactory('UpkeepAutoFunder') - upkeepTranscoderFactory = await ethers.getContractFactory('UpkeepTranscoder') -}) - -describe.skip('KeeperRegistry1_2', () => { - const linkEth = BigNumber.from(300000000) - const gasWei = BigNumber.from(100) - const linkDivisibility = BigNumber.from('1000000000000000000') - const executeGas = BigNumber.from('100000') - const paymentPremiumBase = BigNumber.from('1000000000') - const paymentPremiumPPB = BigNumber.from('250000000') - const flatFeeMicroLink = BigNumber.from(0) - const blockCountPerTurn = BigNumber.from(3) - const emptyBytes = '0x00' - const randomBytes = '0x1234abcd' - const zeroAddress = ethers.constants.AddressZero - const extraGas = BigNumber.from('250000') - const registryGasOverhead = BigNumber.from('80000') - const stalenessSeconds = BigNumber.from(43820) - const gasCeilingMultiplier = BigNumber.from(1) - const checkGasLimit = BigNumber.from(20000000) - const fallbackGasPrice = BigNumber.from(200) - const fallbackLinkPrice = BigNumber.from(200000000) - const maxPerformGas = BigNumber.from(5000000) - const minUpkeepSpend = BigNumber.from(0) - - let owner: Signer - let keeper1: Signer - let keeper2: Signer - let keeper3: Signer - let nonkeeper: Signer - let admin: Signer - let payee1: Signer - let payee2: Signer - let payee3: Signer - - let linkToken: LinkToken - let linkEthFeed: MockV3Aggregator - let gasPriceFeed: MockV3Aggregator - let registry: KeeperRegistry - let registry2: KeeperRegistry - let mock: UpkeepMock - let transcoder: UpkeepTranscoder - - let id: BigNumber - let keepers: string[] - let payees: string[] - - beforeEach(async () => { - owner = personas.Default - keeper1 = personas.Carol - keeper2 = personas.Eddy - keeper3 = personas.Nancy - nonkeeper = personas.Ned - admin = personas.Neil - payee1 = personas.Nelly - payee2 = personas.Norbert - payee3 = personas.Nick - - keepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - ] - - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - registry = await keeperRegistryFactory - .connect(owner) - .deploy(linkToken.address, linkEthFeed.address, gasPriceFeed.address, { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - registry2 = await keeperRegistryFactory - .connect(owner) - .deploy(linkToken.address, linkEthFeed.address, gasPriceFeed.address, { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - mock = await upkeepMockFactory.deploy() - await linkToken - .connect(owner) - .transfer(await keeper1.getAddress(), toWei('1000')) - await linkToken - .connect(owner) - .transfer(await keeper2.getAddress(), toWei('1000')) - await linkToken - .connect(owner) - .transfer(await keeper3.getAddress(), toWei('1000')) - - await registry.connect(owner).setKeepers(keepers, payees) - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - ) - id = await getUpkeepID(tx) - }) - - const linkForGas = ( - upkeepGasSpent: BigNumberish, - premiumPPB?: BigNumberish, - flatFee?: BigNumberish, - ) => { - premiumPPB = premiumPPB === undefined ? paymentPremiumPPB : premiumPPB - flatFee = flatFee === undefined ? flatFeeMicroLink : flatFee - const gasSpent = registryGasOverhead.add(BigNumber.from(upkeepGasSpent)) - const base = gasWei.mul(gasSpent).mul(linkDivisibility).div(linkEth) - const premium = base.mul(premiumPPB).div(paymentPremiumBase) - const flatFeeJules = BigNumber.from(flatFee).mul('1000000000000') - return base.add(premium).add(flatFeeJules) - } - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registry.typeAndVersion() - assert.equal(typeAndVersion, 'KeeperRegistry 1.2.0') - }) - }) - - describe('#setKeepers', () => { - const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF' - it('reverts when not called by the owner', async () => { - await evmRevert( - registry.connect(keeper1).setKeepers([], []), - 'Only callable by owner', - ) - }) - - it('reverts when adding the same keeper twice', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper1.getAddress()], - [await payee1.getAddress(), await payee1.getAddress()], - ), - 'DuplicateEntry()', - ) - }) - - it('reverts with different numbers of keepers/payees', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [await payee1.getAddress()], - ), - 'ParameterLengthError()', - ) - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress()], - [await payee1.getAddress(), await payee2.getAddress()], - ), - 'ParameterLengthError()', - ) - }) - - it('reverts if the payee is the zero address', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [ - await payee1.getAddress(), - '0x0000000000000000000000000000000000000000', - ], - ), - 'InvalidPayee()', - ) - }) - - it('emits events for every keeper added and removed', async () => { - const oldKeepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - ] - const oldPayees = [await payee1.getAddress(), await payee2.getAddress()] - await registry.connect(owner).setKeepers(oldKeepers, oldPayees) - assert.deepEqual(oldKeepers, (await registry.getState()).keepers) - - // remove keepers - const newKeepers = [ - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - const newPayees = [await payee2.getAddress(), await payee3.getAddress()] - const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees) - assert.deepEqual(newKeepers, (await registry.getState()).keepers) - - await expect(tx) - .to.emit(registry, 'KeepersUpdated') - .withArgs(newKeepers, newPayees) - }) - - it('updates the keeper to inactive when removed', async () => { - await registry.connect(owner).setKeepers(keepers, payees) - await registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper3.getAddress()], - [await payee1.getAddress(), await payee3.getAddress()], - ) - const added = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.isTrue(added.active) - const removed = await registry.getKeeperInfo(await keeper2.getAddress()) - assert.isFalse(removed.active) - }) - - it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => { - const oldKeepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - ] - const oldPayees = [await payee1.getAddress(), await payee2.getAddress()] - await registry.connect(owner).setKeepers(oldKeepers, oldPayees) - assert.deepEqual(oldKeepers, (await registry.getState()).keepers) - - const newKeepers = [ - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - const newPayees = [IGNORE_ADDRESS, await payee3.getAddress()] - const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees) - assert.deepEqual(newKeepers, (await registry.getState()).keepers) - - const ignored = await registry.getKeeperInfo(await keeper2.getAddress()) - assert.equal(await payee2.getAddress(), ignored.payee) - assert.equal(true, ignored.active) - - await expect(tx) - .to.emit(registry, 'KeepersUpdated') - .withArgs(newKeepers, newPayees) - }) - - it('reverts if the owner changes the payee', async () => { - await registry.connect(owner).setKeepers(keepers, payees) - await evmRevert( - registry - .connect(owner) - .setKeepers(keepers, [ - await payee1.getAddress(), - await payee2.getAddress(), - await owner.getAddress(), - ]), - 'InvalidPayee()', - ) - }) - }) - - describe('#registerUpkeep', () => { - context('and the registry is paused', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - it('reverts', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - zeroAddress, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'Pausable: paused', - ) - }) - }) - - it('reverts if the target is not a contract', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - zeroAddress, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'NotAContract()', - ) - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry - .connect(keeper1) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'OnlyCallableByOwnerOrRegistrar()', - ) - }) - - it('reverts if execute gas is too low', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 2299, - await admin.getAddress(), - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('reverts if execute gas is too high', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 5000001, - await admin.getAddress(), - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('creates a record of the registration', async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - id = await getUpkeepID(tx) - await expect(tx) - .to.emit(registry, 'UpkeepRegistered') - .withArgs(id, executeGas, await admin.getAddress()) - const registration = await registry.getUpkeep(id) - assert.equal(mock.address, registration.target) - assert.equal(0, registration.balance.toNumber()) - assert.equal(emptyBytes, registration.checkData) - assert(registration.maxValidBlocknumber.eq('0xffffffffffffffff')) - }) - }) - - describe('#addFunds', () => { - const amount = toWei('1') - - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - }) - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).addFunds(id.add(1), amount), - 'UpkeepNotActive()', - ) - }) - - it('adds to the balance of the registration', async () => { - await registry.connect(keeper1).addFunds(id, amount) - const registration = await registry.getUpkeep(id) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('emits a log', async () => { - const tx = await registry.connect(keeper1).addFunds(id, amount) - await expect(tx) - .to.emit(registry, 'FundsAdded') - .withArgs(id, await keeper1.getAddress(), amount) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).addFunds(id, amount), - 'UpkeepNotActive()', - ) - }) - }) - - describe('#setUpkeepGasLimit', () => { - const newGasLimit = BigNumber.from('500000') - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).setUpkeepGasLimit(id.add(1), newGasLimit), - 'UpkeepNotActive()', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).setUpkeepGasLimit(id, newGasLimit), - 'UpkeepNotActive()', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry.connect(owner).setUpkeepGasLimit(id, newGasLimit), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if new gas limit is out of bounds', async () => { - await evmRevert( - registry.connect(admin).setUpkeepGasLimit(id, BigNumber.from('100')), - 'GasLimitOutsideRange()', - ) - await evmRevert( - registry - .connect(admin) - .setUpkeepGasLimit(id, BigNumber.from('6000000')), - 'GasLimitOutsideRange()', - ) - }) - - it('updates the gas limit successfully', async () => { - const initialGasLimit = (await registry.getUpkeep(id)).executeGas - assert.equal(initialGasLimit, executeGas.toNumber()) - await registry.connect(admin).setUpkeepGasLimit(id, newGasLimit) - const updatedGasLimit = (await registry.getUpkeep(id)).executeGas - assert.equal(updatedGasLimit, newGasLimit.toNumber()) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepGasLimit(id, newGasLimit) - await expect(tx) - .to.emit(registry, 'UpkeepGasLimitSet') - .withArgs(id, newGasLimit) - }) - }) - - describe('#checkUpkeep', () => { - it('reverts if the upkeep is not funded', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'InsufficientFunds()', - ) - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - }) - - it('reverts if executed', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry.checkUpkeep(id, await keeper1.getAddress()), - 'OnlySimulatedBackend()', - ) - }) - - it('reverts if the specified keeper is not valid', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry.checkUpkeep(id, await owner.getAddress()), - 'OnlySimulatedBackend()', - ) - }) - - context('and upkeep is not needed', () => { - beforeEach(async () => { - await mock.setCanCheck(false) - }) - - it('reverts', async () => { - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'UpkeepNotNeeded()', - ) - }) - }) - - context('and the upkeep check fails', () => { - beforeEach(async () => { - const reverter = await upkeepReverterFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - reverter.address, - 2500000, - await admin.getAddress(), - emptyBytes, - ) - id = await getUpkeepID(tx) - await linkToken - .connect(keeper1) - .approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - }) - - it('reverts', async () => { - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'TargetCheckReverted', - ) - }) - }) - - context('and upkeep check simulations succeeds', () => { - beforeEach(async () => { - await mock.setCanCheck(true) - await mock.setCanPerform(true) - }) - - it('returns true with pricing info if the target can execute', async () => { - const newGasMultiplier = BigNumber.from(10) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: newGasMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const response = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()) - assert.isTrue(response.gasLimit.eq(executeGas)) - assert.isTrue(response.linkEth.eq(linkEth)) - assert.isTrue( - response.adjustedGasWei.eq(gasWei.mul(newGasMultiplier)), - ) - assert.isTrue( - response.maxLinkPayment.eq( - linkForGas(executeGas.toNumber()).mul(newGasMultiplier), - ), - ) - }) - - it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => { - await mock.setCheckGasToBurn(checkGasLimit) - await mock.setPerformGasToBurn(executeGas) - const gas = checkGasLimit - .add(executeGas) - .add(PERFORM_GAS_OVERHEAD) - .add(CHECK_GAS_OVERHEAD) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress(), { - gasLimit: gas, - }) - }) - }) - }) - }) - - describe('#performUpkeep', () => { - let _lastKeeper = keeper1 - - async function getPerformPaymentAmount() { - _lastKeeper = _lastKeeper === keeper1 ? keeper2 : keeper1 - const before = ( - await registry.getKeeperInfo(await _lastKeeper.getAddress()) - ).balance - await registry.connect(_lastKeeper).performUpkeep(id, '0x') - const after = ( - await registry.getKeeperInfo(await _lastKeeper.getAddress()) - ).balance - const difference = after.sub(before) - return difference - } - - it('reverts if the registration is not funded', async () => { - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'InsufficientFunds()', - ) - }) - - context('and the registry is paused', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts', async () => { - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'Pausable: paused', - ) - }) - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - }) - - it('does not revert if the target cannot execute', async () => { - const mockResponse = await mock - .connect(zeroAddress) - .callStatic.checkUpkeep('0x') - assert.isFalse(mockResponse.callable) - - await registry.connect(keeper3).performUpkeep(id, '0x') - }) - - it('returns false if the target cannot execute', async () => { - const mockResponse = await mock - .connect(zeroAddress) - .callStatic.checkUpkeep('0x') - assert.isFalse(mockResponse.callable) - - assert.isFalse( - await registry.connect(keeper1).callStatic.performUpkeep(id, '0x'), - ) - }) - - it('returns true if called', async () => { - await mock.setCanPerform(true) - - const response = await registry - .connect(keeper1) - .callStatic.performUpkeep(id, '0x') - assert.isTrue(response) - }) - - it('reverts if not enough gas supplied', async () => { - await mock.setCanPerform(true) - - await evmRevert( - registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasLimit: BigNumber.from('120000') }), - ) - }) - - it('executes the data passed to the registry', async () => { - await mock.setCanPerform(true) - - const performData = '0xc0ffeec0ffee' - const tx = await registry - .connect(keeper1) - .performUpkeep(id, performData, { gasLimit: extraGas }) - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 2) - assert.equal(eventLog?.[1].event, 'UpkeepPerformed') - expect(eventLog?.[1].args?.[0]).to.equal(id) - assert.equal(eventLog?.[1].args?.[1], true) - assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress()) - assert.isNotEmpty(eventLog?.[1].args?.[3]) - assert.equal(eventLog?.[1].args?.[4], performData) - }) - - it('updates payment balances', async () => { - const keeperBefore = await registry.getKeeperInfo( - await keeper1.getAddress(), - ) - const registrationBefore = await registry.getUpkeep(id) - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const keeperAfter = await registry.getKeeperInfo( - await keeper1.getAddress(), - ) - const registrationAfter = await registry.getUpkeep(id) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(keeperAfter.balance.gt(keeperBefore.balance)) - assert.isTrue(registrationBefore.balance.gt(registrationAfter.balance)) - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - }) - - it('updates amount spent correctly', async () => { - const registrationBefore = await registry.getUpkeep(id) - const balanceBefore = registrationBefore.balance - const amountSpentBefore = registrationBefore.amountSpent - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const registrationAfter = await registry.getUpkeep(id) - const balanceAfter = registrationAfter.balance - const amountSpentAfter = registrationAfter.amountSpent - - assert.isTrue(balanceAfter.lt(balanceBefore)) - assert.isTrue(amountSpentAfter.gt(amountSpentBefore)) - assert.isTrue( - amountSpentAfter - .sub(amountSpentBefore) - .eq(balanceBefore.sub(balanceAfter)), - ) - }) - - it('only pays for gas used [ @skip-coverage ]', async () => { - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry.connect(keeper1).performUpkeep(id, '0x') - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas.toNumber()) - const totalTx = linkForGas(receipt.gasUsed.toNumber()) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).lt(difference)) // exact number is flaky - assert.isTrue(linkForGas(6000).gt(difference)) // instead test a range - }) - - it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => { - const multiplier = BigNumber.from(10) - const gasPrice = BigNumber.from('1000000000') // 10M x the gas feed's rate - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasPrice }) - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas).mul(multiplier) - const totalTx = linkForGas(receipt.gasUsed).mul(multiplier) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).mul(multiplier).lt(difference)) - assert.isTrue(linkForGas(6000).mul(multiplier).gt(difference)) - }) - - it('only pays as much as the node spent [ @skip-coverage ]', async () => { - const multiplier = BigNumber.from(10) - const gasPrice = BigNumber.from(200) // 2X the gas feed's rate - const effectiveMultiplier = BigNumber.from(2) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasPrice }) - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas.toNumber()).mul(effectiveMultiplier) - const totalTx = linkForGas(receipt.gasUsed).mul(effectiveMultiplier) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).mul(effectiveMultiplier).lt(difference)) - assert.isTrue(linkForGas(6000).mul(effectiveMultiplier).gt(difference)) - }) - - it('pays the caller even if the target function fails', async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id = await getUpkeepID(tx) - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - const keeperBalanceBefore = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const keeperBalanceAfter = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - assert.isTrue(keeperBalanceAfter.gt(keeperBalanceBefore)) - }) - - it('reverts if called by a non-keeper', async () => { - await evmRevert( - registry.connect(nonkeeper).performUpkeep(id, '0x'), - 'OnlyActiveKeepers()', - ) - }) - - it('reverts if the upkeep has been canceled', async () => { - await mock.setCanPerform(true) - - await registry.connect(owner).cancelUpkeep(id) - - await evmRevert( - registry.connect(keeper1).performUpkeep(id, '0x'), - 'UpkeepNotActive()', - ) - }) - - it('uses the fallback gas price if the feed price is stale [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const answer = 100 - const updatedAt = 946684800 // New Years 2000 🥳 - const startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - const amountWithStaleFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithStaleFeed)) - }) - - it('uses the fallback gas price if the feed price is non-sensical [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const currentBlockNum = await ethers.provider.getBlockNumber() - const currentBlock = await ethers.provider.getBlock(currentBlockNum) - const updatedAt = currentBlock.timestamp - const startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - const amountWithNegativeFeed = await getPerformPaymentAmount() - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - const amountWithZeroFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithNegativeFeed)) - assert.isTrue(normalAmount.lt(amountWithZeroFeed)) - }) - - it('uses the fallback if the link price feed is stale', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const answer = 100 - const updatedAt = 946684800 // New Years 2000 🥳 - const startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - const amountWithStaleFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithStaleFeed)) - }) - - it('uses the fallback link price if the feed price is non-sensical [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const currentBlockNum = await ethers.provider.getBlockNumber() - const currentBlock = await ethers.provider.getBlock(currentBlockNum) - const updatedAt = currentBlock.timestamp - const startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - const amountWithNegativeFeed = await getPerformPaymentAmount() - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - const amountWithZeroFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithNegativeFeed)) - assert.isTrue(normalAmount.lt(amountWithZeroFeed)) - }) - - it('reverts if the same caller calls twice in a row', async () => { - await registry.connect(keeper1).performUpkeep(id, '0x') - await evmRevert( - registry.connect(keeper1).performUpkeep(id, '0x'), - 'KeepersMustTakeTurns()', - ) - await registry.connect(keeper2).performUpkeep(id, '0x') - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'KeepersMustTakeTurns()', - ) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => { - await mock.setPerformGasToBurn(executeGas) - await mock.setCanPerform(true) - const gas = executeGas.add(PERFORM_GAS_OVERHEAD) - const performData = '0xc0ffeec0ffee' - const tx = await registry - .connect(keeper1) - .performUpkeep(id, performData, { gasLimit: gas }) - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 2) - assert.equal(eventLog?.[1].event, 'UpkeepPerformed') - expect(eventLog?.[1].args?.[0]).to.equal(id) - assert.equal(eventLog?.[1].args?.[1], true) - assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress()) - assert.isNotEmpty(eventLog?.[1].args?.[3]) - assert.equal(eventLog?.[1].args?.[4], performData) - }) - - it('can self fund', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - emptyBytes, - ) - const upkeepID = await getUpkeepID(tx) - await autoFunderUpkeep.setUpkeepId(upkeepID) - // Give enough funds for upkeep as well as to the upkeep contract - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - await linkToken - .connect(owner) - .transfer(autoFunderUpkeep.address, toWei('1000')) - let maxPayment = await registry.getMaxPaymentForGas(executeGas) - - // First set auto funding amount to 0 and verify that balance is deducted upon performUpkeep - let initialBalance = toWei('100') - await registry.connect(owner).addFunds(upkeepID, initialBalance) - await autoFunderUpkeep.setAutoFundLink(0) - await autoFunderUpkeep.setIsEligible(true) - await registry.connect(keeper1).performUpkeep(upkeepID, '0x') - - let postUpkeepBalance = (await registry.getUpkeep(upkeepID)).balance - assert.isTrue(postUpkeepBalance.lt(initialBalance)) // Balance should be deducted - assert.isTrue(postUpkeepBalance.gte(initialBalance.sub(maxPayment))) // Balance should not be deducted more than maxPayment - - // Now set auto funding amount to 100 wei and verify that the balance increases - initialBalance = postUpkeepBalance - let autoTopupAmount = toWei('100') - await autoFunderUpkeep.setAutoFundLink(autoTopupAmount) - await autoFunderUpkeep.setIsEligible(true) - await registry.connect(keeper2).performUpkeep(upkeepID, '0x') - - postUpkeepBalance = (await registry.getUpkeep(upkeepID)).balance - // Balance should increase by autoTopupAmount and decrease by max maxPayment - assert.isTrue( - postUpkeepBalance.gte( - initialBalance.add(autoTopupAmount).sub(maxPayment), - ), - ) - }) - - it('can self cancel', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - emptyBytes, - ) - const upkeepID = await getUpkeepID(tx) - await autoFunderUpkeep.setUpkeepId(upkeepID) - - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - await registry.connect(owner).addFunds(upkeepID, toWei('100')) - await autoFunderUpkeep.setIsEligible(true) - await autoFunderUpkeep.setShouldCancel(true) - - let registration = await registry.getUpkeep(upkeepID) - const oldExpiration = registration.maxValidBlocknumber - - // Do the thing - await registry.connect(keeper1).performUpkeep(upkeepID, '0x') - - // Verify upkeep gets cancelled - registration = await registry.getUpkeep(upkeepID) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - }) - }) - - describe('#withdrawFunds', () => { - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry - .connect(owner) - .withdrawFunds(id.add(1), await payee1.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if called on an uncanceled upkeep', async () => { - await evmRevert( - registry.connect(admin).withdrawFunds(id, await payee1.getAddress()), - 'UpkeepNotCanceled()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry.connect(admin).withdrawFunds(id, zeroAddress), - 'InvalidRecipient()', - ) - }) - - describe('after the registration is cancelled', () => { - beforeEach(async () => { - await registry.connect(owner).cancelUpkeep(id) - }) - - it('moves the funds out and updates the balance', async () => { - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const registryBefore = await linkToken.balanceOf(registry.address) - - let registration = await registry.getUpkeep(id) - let previousBalance = registration.balance - - await registry - .connect(admin) - .withdrawFunds(id, await payee1.getAddress()) - - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - const registryAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(payee1Before.add(previousBalance).eq(payee1After)) - assert.isTrue(registryBefore.sub(previousBalance).eq(registryAfter)) - - registration = await registry.getUpkeep(id) - assert.equal(0, registration.balance.toNumber()) - }) - - it('deducts cancellation fees from upkeep and gives to owner', async () => { - let minUpkeepSpend = toWei('10') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - let amountSpent = toWei('100').sub(upkeepBefore) - let cancellationFee = minUpkeepSpend.sub(amountSpent) - - await registry - .connect(admin) - .withdrawFunds(id, await payee1.getAddress()) - - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - let upkeepAfter = (await registry.getUpkeep(id)).balance - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // Post upkeep balance should be 0 - assert.equal(0, upkeepAfter.toNumber()) - // balance - cancellationFee should be transferred to payee - assert.isTrue( - payee1Before.add(upkeepBefore.sub(cancellationFee)).eq(payee1After), - ) - assert.isTrue(ownerAfter.eq(cancellationFee)) - }) - - it('deducts max upto balance as cancellation fees', async () => { - // Very high min spend, should deduct whole balance as cancellation fees - let minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - await registry - .connect(admin) - .withdrawFunds(id, await payee1.getAddress()) - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - let upkeepAfter = (await registry.getUpkeep(id)).balance - - assert.equal(0, upkeepAfter.toNumber()) - // No funds should be transferred, all of upkeepBefore should be given to owner - assert.isTrue(payee1After.eq(payee1Before)) - assert.isTrue(ownerAfter.eq(upkeepBefore)) - }) - - it('does not deduct cancellation fees if enough is spent', async () => { - // Very low min spend, already spent in one upkeep - let minUpkeepSpend = BigNumber.from(420) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - await registry - .connect(admin) - .withdrawFunds(id, await payee1.getAddress()) - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - let upkeepAfter = (await registry.getUpkeep(id)).balance - - assert.equal(0, upkeepAfter.toNumber()) - // No cancellation fees for owner - assert.equal(0, ownerAfter.toNumber()) - // Whole balance transferred to payee - assert.isTrue(payee1Before.add(upkeepBefore).eq(payee1After)) - }) - }) - }) - - describe('#withdrawOwnerFunds', () => { - it('can only be called by owner', async () => { - await evmRevert( - registry.connect(keeper1).withdrawOwnerFunds(), - 'Only callable by owner', - ) - }) - - it('withdraws the collected fees to owner', async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - // Very high min spend, whole balance as cancellation fees - let minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - let upkeepBalance = (await registry.getUpkeep(id)).balance - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).cancelUpkeep(id) - await registry.connect(admin).withdrawFunds(id, await payee1.getAddress()) - // Transfered to owner balance on registry - let ownerRegistryBalance = (await registry.getState()).state - .ownerLinkBalance - assert.isTrue(ownerRegistryBalance.eq(upkeepBalance)) - - // Now withdraw - await registry.connect(owner).withdrawOwnerFunds() - - ownerRegistryBalance = (await registry.getState()).state.ownerLinkBalance - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - // Owner registry balance should be changed to 0 - assert.isTrue(ownerRegistryBalance.eq(BigNumber.from('0'))) - - // Owner should be credited with the balance - assert.isTrue(ownerBefore.add(upkeepBalance).eq(ownerAfter)) - }) - }) - - describe('#cancelUpkeep', () => { - it('reverts if the ID is not valid', async () => { - await evmRevert( - registry.connect(owner).cancelUpkeep(id.add(1)), - 'CannotCancel()', - ) - }) - - it('reverts if called by a non-owner/non-admin', async () => { - await evmRevert( - registry.connect(keeper1).cancelUpkeep(id), - 'OnlyCallableByOwnerOrAdmin()', - ) - }) - - describe('when called by the owner', async () => { - it('sets the registration to invalid immediately', async () => { - const tx = await registry.connect(owner).cancelUpkeep(id) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(id) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).cancelUpkeep(id) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(id, BigNumber.from(receipt.blockNumber)) - }) - - it('immediately prevents upkeep', async () => { - await registry.connect(owner).cancelUpkeep(id) - - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'UpkeepNotActive()', - ) - }) - - it('does not revert if reverts if called multiple times', async () => { - await registry.connect(owner).cancelUpkeep(id) - await evmRevert( - registry.connect(owner).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - - describe('when called by the owner when the admin has just canceled', () => { - let oldExpiration: BigNumber - - beforeEach(async () => { - await registry.connect(admin).cancelUpkeep(id) - const registration = await registry.getUpkeep(id) - oldExpiration = registration.maxValidBlocknumber - }) - - it('allows the owner to cancel it more quickly', async () => { - await registry.connect(owner).cancelUpkeep(id) - - const registration = await registry.getUpkeep(id) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - }) - }) - - describe('when called by the admin', async () => { - const delay = 50 - - it('sets the registration to invalid in 50 blocks', async () => { - const tx = await registry.connect(admin).cancelUpkeep(id) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(id) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber + 50, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(admin).cancelUpkeep(id) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(id, BigNumber.from(receipt.blockNumber + delay)) - }) - - // it('updates the canceled registrations list', async () => { - // let canceled = await registry.callStatic.getCanceledUpkeepList() - // assert.deepEqual([], canceled) - - // await registry.connect(admin).cancelUpkeep(id) - - // canceled = await registry.callStatic.getCanceledUpkeepList() - // assert.deepEqual([id], canceled) - // }) - - it('immediately prevents upkeep', async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.connect(admin).cancelUpkeep(id) - await registry.connect(keeper2).performUpkeep(id, '0x') // still works - - for (let i = 0; i < delay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'UpkeepNotActive()', - ) - }) - - it('reverts if called again by the admin', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry.connect(admin).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - - // it('does not revert or double add the cancellation record if called by the owner immediately after', async () => { - // await registry.connect(admin).cancelUpkeep(id) - - // await registry.connect(owner).cancelUpkeep(id) - - // const canceled = await registry.callStatic.getCanceledUpkeepList() - // assert.deepEqual([id], canceled) - // }) - - it('reverts if called by the owner after the timeout', async () => { - await registry.connect(admin).cancelUpkeep(id) - - for (let i = 0; i < delay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevert( - registry.connect(owner).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - }) - }) - - describe('#withdrawPayment', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('reverts if called by anyone but the payee', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment(await keeper1.getAddress(), zeroAddress), - 'InvalidRecipient()', - ) - }) - - it('updates the balances', async () => { - const to = await nonkeeper.getAddress() - const keeperBefore = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const registrationBefore = (await registry.getUpkeep(id)).balance - const toLinkBefore = await linkToken.balanceOf(to) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - - //// Do the thing - await registry - .connect(payee1) - .withdrawPayment(await keeper1.getAddress(), to) - - const keeperAfter = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const registrationAfter = (await registry.getUpkeep(id)).balance - const toLinkAfter = await linkToken.balanceOf(to) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(keeperAfter.eq(BigNumber.from(0))) - assert.isTrue(registrationBefore.eq(registrationAfter)) - assert.isTrue(toLinkBefore.add(keeperBefore).eq(toLinkAfter)) - assert.isTrue(registryLinkBefore.sub(keeperBefore).eq(registryLinkAfter)) - }) - - it('emits a log announcing the withdrawal', async () => { - const balance = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - const tx = await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PaymentWithdrawn') - .withArgs( - await keeper1.getAddress(), - balance, - await nonkeeper.getAddress(), - await payee1.getAddress(), - ) - }) - }) - - describe('#transferPayeeship', () => { - it('reverts when called by anyone but the current payee', async () => { - await evmRevert( - registry - .connect(payee2) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevert( - registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee1.getAddress(), - ), - 'ValueNotChanged()', - ) - }) - - it('does not change the payee', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const info = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.equal(await payee1.getAddress(), info.payee) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferRequested') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does not emit an event when called with the same proposal', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptPayeeship', () => { - beforeEach(async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('reverts when called by anyone but the proposed payee', async () => { - await evmRevert( - registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()), - 'OnlyCallableByProposedPayee()', - ) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee2) - .acceptPayeeship(await keeper1.getAddress()) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferred') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does change the payee', async () => { - await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress()) - - const info = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.equal(await payee2.getAddress(), info.payee) - }) - }) - - describe('#setConfig', () => { - const payment = BigNumber.from(1) - const flatFee = BigNumber.from(2) - const checks = BigNumber.from(3) - const staleness = BigNumber.from(4) - const ceiling = BigNumber.from(5) - const maxGas = BigNumber.from(6) - const fbGasEth = BigNumber.from(7) - const fbLinkEth = BigNumber.from(8) - - it('reverts when called by anyone but the proposed owner', async () => { - await evmRevert( - registry.connect(payee1).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - 'Only callable by owner', - ) - }) - - it('updates the config', async () => { - const old = (await registry.getState()).config - assert.isTrue(paymentPremiumPPB.eq(old.paymentPremiumPPB)) - assert.isTrue(flatFeeMicroLink.eq(old.flatFeeMicroLink)) - assert.isTrue(blockCountPerTurn.eq(old.blockCountPerTurn)) - assert.isTrue(stalenessSeconds.eq(old.stalenessSeconds)) - assert.isTrue(gasCeilingMultiplier.eq(old.gasCeilingMultiplier)) - - await registry.connect(owner).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const updated = (await registry.getState()).config - assert.equal(updated.paymentPremiumPPB, payment.toNumber()) - assert.equal(updated.flatFeeMicroLink, flatFee.toNumber()) - assert.equal(updated.blockCountPerTurn, checks.toNumber()) - assert.equal(updated.stalenessSeconds, staleness.toNumber()) - assert.equal(updated.gasCeilingMultiplier, ceiling.toNumber()) - assert.equal(updated.checkGasLimit, maxGas.toNumber()) - assert.equal(updated.fallbackGasPrice.toNumber(), fbGasEth.toNumber()) - assert.equal(updated.fallbackLinkPrice.toNumber(), fbLinkEth.toNumber()) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - await expect(tx) - .to.emit(registry, 'ConfigSet') - .withArgs([ - payment, - flatFee, - checks, - maxGas, - staleness, - ceiling, - minUpkeepSpend, - maxPerformGas, - fbGasEth, - fbLinkEth, - ]) - }) - }) - - describe('#onTokenTransfer', () => { - const amount = toWei('1') - - it('reverts if not called by the LINK token', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id]) - - await evmRevert( - registry - .connect(keeper1) - .onTokenTransfer(await keeper1.getAddress(), amount, data), - 'OnlyCallableByLINKToken()', - ) - }) - - it('reverts if not called with more or less than 32 bytes', async () => { - const longData = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256'], - ['33', '34'], - ) - const shortData = '0x12345678' - - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, longData), - ) - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, shortData), - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).addFunds(id, amount), - 'UpkeepNotActive()', - ) - }) - - it('updates the funds of the job id passed', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id]) - - const before = (await registry.getUpkeep(id)).balance - await linkToken - .connect(owner) - .transferAndCall(registry.address, amount, data) - const after = (await registry.getUpkeep(id)).balance - - assert.isTrue(before.add(amount).eq(after)) - }) - }) - - describe('#recoverFunds', () => { - const sent = toWei('7') - - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - - // add funds to upkeep 1 and perform and withdraw some payment - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id1 = await getUpkeepID(tx) - await registry.connect(keeper1).addFunds(id1, toWei('5')) - await registry.connect(keeper1).performUpkeep(id1, '0x') - await registry.connect(keeper2).performUpkeep(id1, '0x') - await registry.connect(keeper3).performUpkeep(id1, '0x') - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds directly to the registry - await linkToken.connect(keeper1).transfer(registry.address, sent) - - // add funds to upkeep 2 and perform and withdraw some payment - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id2 = await getUpkeepID(tx2) - await registry.connect(keeper1).addFunds(id2, toWei('5')) - await registry.connect(keeper1).performUpkeep(id2, '0x') - await registry.connect(keeper2).performUpkeep(id2, '0x') - await registry.connect(keeper3).performUpkeep(id2, '0x') - await registry - .connect(payee2) - .withdrawPayment( - await keeper2.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds using onTokenTransfer - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id2]) - await linkToken - .connect(owner) - .transferAndCall(registry.address, toWei('1'), data) - - // remove a keeper - await registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [await payee1.getAddress(), await payee2.getAddress()], - ) - - // withdraw some funds - await registry.connect(owner).cancelUpkeep(id1) - await registry.connect(admin).withdrawFunds(id1, await admin.getAddress()) - }) - - it('reverts if not called by owner', async () => { - await evmRevert( - registry.connect(keeper1).recoverFunds(), - 'Only callable by owner', - ) - }) - - it('allows any funds that have been accidentally transfered to be moved', async () => { - const balanceBefore = await linkToken.balanceOf(registry.address) - - await linkToken.balanceOf(registry.address) - - await registry.connect(owner).recoverFunds() - const balanceAfter = await linkToken.balanceOf(registry.address) - assert.isTrue(balanceBefore.eq(balanceAfter.add(sent))) - }) - }) - - describe('#pause', () => { - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).pause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse(await registry.paused()) - - await registry.connect(owner).pause() - - assert.isTrue(await registry.paused()) - }) - }) - - describe('#unpause', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).unpause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as not paused', async () => { - assert.isTrue(await registry.paused()) - - await registry.connect(owner).unpause() - - assert.isFalse(await registry.paused()) - }) - }) - - describe('#getMaxPaymentForGas', () => { - const gasAmounts = [100000, 10000000] - const premiums = [0, 250000000] - const flatFees = [0, 1000000] - it('calculates the max fee approptiately', async () => { - for (let idx = 0; idx < gasAmounts.length; idx++) { - const gas = gasAmounts[idx] - for (let jdx = 0; jdx < premiums.length; jdx++) { - const premium = premiums[jdx] - for (let kdx = 0; kdx < flatFees.length; kdx++) { - const flatFee = flatFees[kdx] - await registry.connect(owner).setConfig({ - paymentPremiumPPB: premium, - flatFeeMicroLink: flatFee, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const price = await registry.getMaxPaymentForGas(gas) - expect(price).to.equal(linkForGas(gas, premium, flatFee)) - } - } - } - }) - }) - - describe('#setPeerRegistryMigrationPermission() / #getPeerRegistryMigrationPermission()', () => { - const peer = randomAddress() - it('allows the owner to set the peer registries', async () => { - let permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - await registry.setPeerRegistryMigrationPermission(peer, 1) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(1) - await registry.setPeerRegistryMigrationPermission(peer, 2) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(2) - await registry.setPeerRegistryMigrationPermission(peer, 0) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - }) - it('reverts if passed an unsupported permission', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 10), - ).to.be.reverted - }) - it('reverts if not called by the owner', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 1), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('migrateUpkeeps() / #receiveUpkeeps()', async () => { - context('when permissions are set', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - }) - - it('migrates an upkeep', async () => { - expect((await registry.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - // migrate - await registry.connect(admin).migrateUpkeeps([id], registry2.address) - expect((await registry.getState()).state.numUpkeeps).to.equal(0) - expect((await registry2.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(id)).balance).to.equal(0) - expect((await registry.getUpkeep(id)).checkData).to.equal('0x') - expect((await registry2.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry2.getState()).state.expectedLinkBalance).to.equal( - toWei('100'), - ) - expect((await registry2.getUpkeep(id)).checkData).to.equal(randomBytes) - }) - it('emits an event on both contracts', async () => { - expect((await registry.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - const tx = registry - .connect(admin) - .migrateUpkeeps([id], registry2.address) - await expect(tx) - .to.emit(registry, 'UpkeepMigrated') - .withArgs(id, toWei('100'), registry2.address) - await expect(tx) - .to.emit(registry2, 'UpkeepReceived') - .withArgs(id, toWei('100'), registry.address) - }) - it('is only migratable by the admin', async () => { - await expect( - registry.connect(owner).migrateUpkeeps([id], registry2.address), - ).to.be.revertedWith('OnlyCallableByAdmin()') - await registry.connect(admin).migrateUpkeeps([id], registry2.address) - }) - }) - - context('when permissions are not set', () => { - it('reverts', async () => { - // no permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // only outgoing permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // only incoming permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // permissions opposite direction - await registry.setPeerRegistryMigrationPermission(registry2.address, 2) - await registry2.setPeerRegistryMigrationPermission(registry.address, 1) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - }) - }) - }) - - describe('#checkUpkeep / #performUpkeep', () => { - const performData = '0xc0ffeec0ffee' - const multiplier = BigNumber.from(10) - const flatFee = BigNumber.from('100000') //0.1 LINK - const callGasPrice = 1 - - it('uses the same minimum balance calculation [ @skip-coverage ]', async () => { - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink: flatFee, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - await linkToken.connect(owner).approve(registry.address, toWei('100')) - - const tx1 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const upkeepID1 = await getUpkeepID(tx1) - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const upkeepID2 = await getUpkeepID(tx2) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - // upkeep 1 is underfunded, 2 is funded - const minBalance1 = (await registry.getMaxPaymentForGas(executeGas)).sub( - 1, - ) - const minBalance2 = await registry.getMaxPaymentForGas(executeGas) - await registry.connect(owner).addFunds(upkeepID1, minBalance1) - await registry.connect(owner).addFunds(upkeepID2, minBalance2) - // upkeep 1 check should revert, 2 should succeed - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID1, await keeper1.getAddress(), { - gasPrice: callGasPrice, - }), - ) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID2, await keeper1.getAddress(), { - gasPrice: callGasPrice, - }) - // upkeep 1 perform should revert, 2 should succeed - await evmRevert( - registry - .connect(keeper1) - .performUpkeep(upkeepID1, performData, { gasLimit: extraGas }), - 'InsufficientFunds()', - ) - await registry - .connect(keeper1) - .performUpkeep(upkeepID2, performData, { gasLimit: extraGas }) - }) - }) - - describe('#getMinBalanceForUpkeep / #checkUpkeep', () => { - it('calculates the minimum balance appropriately', async () => { - const oneWei = BigNumber.from('1') - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - const minBalance = await registry.getMinBalanceForUpkeep(id) - const tooLow = minBalance.sub(oneWei) - await registry.connect(keeper1).addFunds(id, tooLow) - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'InsufficientFunds()', - ) - await registry.connect(keeper1).addFunds(id, oneWei) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperRegistry1_3.test.ts b/contracts/test/v0.8/automation/KeeperRegistry1_3.test.ts deleted file mode 100644 index 28ed75f475d..00000000000 --- a/contracts/test/v0.8/automation/KeeperRegistry1_3.test.ts +++ /dev/null @@ -1,2641 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { BigNumber, BigNumberish, Signer } from 'ethers' -import { evmRevert } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { toWei } from '../../test-helpers/helpers' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { UpkeepReverter__factory as UpkeepReverterFactory } from '../../../typechain/factories/UpkeepReverter__factory' -import { UpkeepAutoFunder__factory as UpkeepAutoFunderFactory } from '../../../typechain/factories/UpkeepAutoFunder__factory' -import { UpkeepTranscoder__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder__factory' -import { KeeperRegistry1_3__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry1_3__factory' -import { MockArbGasInfo__factory as MockArbGasInfoFactory } from '../../../typechain/factories/MockArbGasInfo__factory' -import { MockOVMGasPriceOracle__factory as MockOVMGasPriceOracleFactory } from '../../../typechain/factories/MockOVMGasPriceOracle__factory' -import { KeeperRegistryLogic1_3__factory as KeeperRegistryLogicFactory } from '../../../typechain/factories/KeeperRegistryLogic1_3__factory' -import { KeeperRegistry1_3 as KeeperRegistry } from '../../../typechain/KeeperRegistry1_3' -import { KeeperRegistryLogic13 as KeeperRegistryLogic } from '../../../typechain/KeeperRegistryLogic13' -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { LinkToken } from '../../../typechain/LinkToken' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { MockArbGasInfo } from '../../../typechain/MockArbGasInfo' -import { MockOVMGasPriceOracle } from '../../../typechain/MockOVMGasPriceOracle' -import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** REGISTRY v1.3 IS FROZEN ************************************/ - -// All tests are disabled for this contract, as we expect it to never change in the future. -// Instead, we test that the bytecode for the contract has not changed. -// If this test ever fails, you should remove it and then re-run the original test suite. - -const BYTECODE = KeeperRegistryFactory.bytecode -const BYTECODE_CHECKSUM = - '0x7e831ebc4e043fc2946449e11f0d170ba5b6085b213591973c437bc5109b1582' - -describe('KeeperRegistry1_3 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal(ethers.utils.id(BYTECODE), BYTECODE_CHECKSUM) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -async function getUpkeepID(tx: any) { - const receipt = await tx.wait() - return receipt.events[0].args.id -} - -function randomAddress() { - return ethers.Wallet.createRandom().address -} - -// ----------------------------------------------------------------------------------------------- -// DEV: these *should* match the perform/check gas overhead values in the contract and on the node -const PERFORM_GAS_OVERHEAD = BigNumber.from(160000) -const CHECK_GAS_OVERHEAD = BigNumber.from(362287) -// ----------------------------------------------------------------------------------------------- - -// Smart contract factories -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory: KeeperRegistryFactory -let keeperRegistryLogicFactory: KeeperRegistryLogicFactory -let upkeepMockFactory: UpkeepMockFactory -let upkeepReverterFactory: UpkeepReverterFactory -let upkeepAutoFunderFactory: UpkeepAutoFunderFactory -let upkeepTranscoderFactory: UpkeepTranscoderFactory -let mockArbGasInfoFactory: MockArbGasInfoFactory -let mockOVMGasPriceOracleFactory: MockOVMGasPriceOracleFactory -let personas: Personas - -before(async () => { - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - // need full path because there are two contracts with name MockV3Aggregator - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - // @ts-ignore bug in autogen file - keeperRegistryFactory = await ethers.getContractFactory('KeeperRegistry1_3') - // @ts-ignore bug in autogen file - keeperRegistryLogicFactory = await ethers.getContractFactory( - 'KeeperRegistryLogic1_3', - ) - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - upkeepReverterFactory = await ethers.getContractFactory('UpkeepReverter') - upkeepAutoFunderFactory = await ethers.getContractFactory('UpkeepAutoFunder') - upkeepTranscoderFactory = await ethers.getContractFactory('UpkeepTranscoder') - mockArbGasInfoFactory = await ethers.getContractFactory('MockArbGasInfo') - mockOVMGasPriceOracleFactory = await ethers.getContractFactory( - 'MockOVMGasPriceOracle', - ) -}) - -describe.skip('KeeperRegistry1_3', () => { - const linkEth = BigNumber.from(300000000) - const gasWei = BigNumber.from(100) - const linkDivisibility = BigNumber.from('1000000000000000000') - const executeGas = BigNumber.from('100000') - const paymentPremiumBase = BigNumber.from('1000000000') - const paymentPremiumPPB = BigNumber.from('250000000') - const premiumMultiplier = BigNumber.from('1000000000') - const flatFeeMicroLink = BigNumber.from(0) - const blockCountPerTurn = BigNumber.from(3) - const emptyBytes = '0x00' - const randomBytes = '0x1234abcd' - const zeroAddress = ethers.constants.AddressZero - const extraGas = BigNumber.from('250000') - const registryGasOverhead = BigNumber.from('80000') - const stalenessSeconds = BigNumber.from(43820) - const gasCeilingMultiplier = BigNumber.from(1) - const checkGasLimit = BigNumber.from(10000000) - const fallbackGasPrice = BigNumber.from(200) - const fallbackLinkPrice = BigNumber.from(200000000) - const maxPerformGas = BigNumber.from(5000000) - const minUpkeepSpend = BigNumber.from(0) - const l1CostWeiArb = BigNumber.from(1000000) - const l1CostWeiOpt = BigNumber.from(2000000) - - let owner: Signer - let keeper1: Signer - let keeper2: Signer - let keeper3: Signer - let nonkeeper: Signer - let admin: Signer - let payee1: Signer - let payee2: Signer - let payee3: Signer - - let linkToken: LinkToken - let linkEthFeed: MockV3Aggregator - let gasPriceFeed: MockV3Aggregator - let registry: KeeperRegistry - let registryLogic: KeeperRegistryLogic - let registry2: KeeperRegistry - let registryLogic2: KeeperRegistryLogic - let mock: UpkeepMock - let transcoder: UpkeepTranscoder - let mockArbGasInfo: MockArbGasInfo - let mockOVMGasPriceOracle: MockOVMGasPriceOracle - - let id: BigNumber - let keepers: string[] - let payees: string[] - - beforeEach(async () => { - owner = personas.Default - keeper1 = personas.Carol - keeper2 = personas.Eddy - keeper3 = personas.Nancy - nonkeeper = personas.Ned - admin = personas.Neil - payee1 = personas.Nelly - payee2 = personas.Norbert - payee3 = personas.Nick - - keepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - ] - - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - mockArbGasInfo = await mockArbGasInfoFactory.connect(owner).deploy() - mockOVMGasPriceOracle = await mockOVMGasPriceOracleFactory - .connect(owner) - .deploy() - - const arbOracleCode = await ethers.provider.send('eth_getCode', [ - mockArbGasInfo.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x000000000000000000000000000000000000006C', - arbOracleCode, - ]) - - const optOracleCode = await ethers.provider.send('eth_getCode', [ - mockOVMGasPriceOracle.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x420000000000000000000000000000000000000F', - optOracleCode, - ]) - - registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - 0, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address, config) - registryLogic2 = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - 0, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - registry2 = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic2.address, config) - mock = await upkeepMockFactory.deploy() - await linkToken - .connect(owner) - .transfer(await keeper1.getAddress(), toWei('1000')) - await linkToken - .connect(owner) - .transfer(await keeper2.getAddress(), toWei('1000')) - await linkToken - .connect(owner) - .transfer(await keeper3.getAddress(), toWei('1000')) - - await registry.connect(owner).setKeepers(keepers, payees) - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - ) - id = await getUpkeepID(tx) - }) - - const linkForGas = ( - upkeepGasSpent: BigNumberish, - premiumPPB?: BigNumberish, - flatFee?: BigNumberish, - l1CostWei?: BigNumber, - ) => { - premiumPPB = premiumPPB === undefined ? paymentPremiumPPB : premiumPPB - flatFee = flatFee === undefined ? flatFeeMicroLink : flatFee - l1CostWei = l1CostWei === undefined ? BigNumber.from(0) : l1CostWei - const gasSpent = registryGasOverhead.add(BigNumber.from(upkeepGasSpent)) - const base = gasWei.mul(gasSpent).mul(linkDivisibility).div(linkEth) - const l1Fee = l1CostWei - .mul(premiumMultiplier) - .mul(paymentPremiumBase.add(premiumPPB)) - .div(linkEth) - const premium = base.mul(premiumPPB).div(paymentPremiumBase) - const flatFeeJules = BigNumber.from(flatFee).mul('1000000000000') - return base.add(premium).add(flatFeeJules).add(l1Fee) - } - - const verifyMaxPayment = async ( - keeperRegistryLogic: KeeperRegistryLogic, - gasAmounts: number[], - premiums: number[], - flatFees: number[], - l1CostWei?: BigNumber, - ) => { - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - - let registry = await keeperRegistryFactory - .connect(owner) - .deploy(keeperRegistryLogic.address, config) - - for (let idx = 0; idx < gasAmounts.length; idx++) { - const gas = gasAmounts[idx] - for (let jdx = 0; jdx < premiums.length; jdx++) { - const premium = premiums[jdx] - for (let kdx = 0; kdx < flatFees.length; kdx++) { - const flatFee = flatFees[kdx] - await registry.connect(owner).setConfig({ - paymentPremiumPPB: premium, - flatFeeMicroLink: flatFee, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const price = await registry.getMaxPaymentForGas(gas) - expect(price).to.equal(linkForGas(gas, premium, flatFee, l1CostWei)) - } - } - } - } - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registry.typeAndVersion() - assert.equal(typeAndVersion, 'KeeperRegistry 1.3.0') - }) - }) - - describe('#setKeepers', () => { - const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF' - it('reverts when not called by the owner', async () => { - await evmRevert( - registry.connect(keeper1).setKeepers([], []), - 'Only callable by owner', - ) - }) - - it('reverts when adding the same keeper twice', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper1.getAddress()], - [await payee1.getAddress(), await payee1.getAddress()], - ), - 'DuplicateEntry()', - ) - }) - - it('reverts with different numbers of keepers/payees', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [await payee1.getAddress()], - ), - 'ParameterLengthError()', - ) - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress()], - [await payee1.getAddress(), await payee2.getAddress()], - ), - 'ParameterLengthError()', - ) - }) - - it('reverts if the payee is the zero address', async () => { - await evmRevert( - registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [ - await payee1.getAddress(), - '0x0000000000000000000000000000000000000000', - ], - ), - 'InvalidPayee()', - ) - }) - - it('emits events for every keeper added and removed', async () => { - const oldKeepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - ] - const oldPayees = [await payee1.getAddress(), await payee2.getAddress()] - await registry.connect(owner).setKeepers(oldKeepers, oldPayees) - assert.deepEqual(oldKeepers, (await registry.getState()).keepers) - - // remove keepers - const newKeepers = [ - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - const newPayees = [await payee2.getAddress(), await payee3.getAddress()] - const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees) - assert.deepEqual(newKeepers, (await registry.getState()).keepers) - - await expect(tx) - .to.emit(registry, 'KeepersUpdated') - .withArgs(newKeepers, newPayees) - }) - - it('updates the keeper to inactive when removed', async () => { - await registry.connect(owner).setKeepers(keepers, payees) - await registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper3.getAddress()], - [await payee1.getAddress(), await payee3.getAddress()], - ) - const added = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.isTrue(added.active) - const removed = await registry.getKeeperInfo(await keeper2.getAddress()) - assert.isFalse(removed.active) - }) - - it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => { - const oldKeepers = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - ] - const oldPayees = [await payee1.getAddress(), await payee2.getAddress()] - await registry.connect(owner).setKeepers(oldKeepers, oldPayees) - assert.deepEqual(oldKeepers, (await registry.getState()).keepers) - - const newKeepers = [ - await keeper2.getAddress(), - await keeper3.getAddress(), - ] - const newPayees = [IGNORE_ADDRESS, await payee3.getAddress()] - const tx = await registry.connect(owner).setKeepers(newKeepers, newPayees) - assert.deepEqual(newKeepers, (await registry.getState()).keepers) - - const ignored = await registry.getKeeperInfo(await keeper2.getAddress()) - assert.equal(await payee2.getAddress(), ignored.payee) - assert.equal(true, ignored.active) - - await expect(tx) - .to.emit(registry, 'KeepersUpdated') - .withArgs(newKeepers, newPayees) - }) - - it('reverts if the owner changes the payee', async () => { - await registry.connect(owner).setKeepers(keepers, payees) - await evmRevert( - registry - .connect(owner) - .setKeepers(keepers, [ - await payee1.getAddress(), - await payee2.getAddress(), - await owner.getAddress(), - ]), - 'InvalidPayee()', - ) - }) - }) - - describe('#pauseUpkeep', () => { - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry.connect(admin).pauseUpkeep(id), - 'UpkeepCancelled()', - ) - }) - - it('reverts if the upkeep is already paused', async () => { - await registry.connect(admin).pauseUpkeep(id) - - await evmRevert( - registry.connect(admin).pauseUpkeep(id), - 'OnlyUnpausedUpkeep()', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await evmRevert( - registry.connect(keeper1).pauseUpkeep(id), - 'OnlyCallableByAdmin()', - ) - }) - - it('pauses the upkeep and emits an event', async () => { - const tx = await registry.connect(admin).pauseUpkeep(id) - await expect(tx).to.emit(registry, 'UpkeepPaused').withArgs(id) - - const registration = await registry.getUpkeep(id) - assert.equal(registration.paused, true) - }) - }) - - describe('#unpauseUpkeep', () => { - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(owner).cancelUpkeep(id) - - await evmRevert( - registry.connect(admin).unpauseUpkeep(id), - 'UpkeepCancelled()', - ) - }) - - it('reverts if the upkeep is not paused', async () => { - await evmRevert( - registry.connect(admin).unpauseUpkeep(id), - 'OnlyPausedUpkeep()', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await registry.connect(admin).pauseUpkeep(id) - - const registration = await registry.getUpkeep(id) - - assert.equal(registration.paused, true) - - await evmRevert( - registry.connect(keeper1).unpauseUpkeep(id), - 'OnlyCallableByAdmin()', - ) - }) - - it('unpauses the upkeep and emits an event', async () => { - await registry.connect(admin).pauseUpkeep(id) - - const tx = await registry.connect(admin).unpauseUpkeep(id) - - await expect(tx).to.emit(registry, 'UpkeepUnpaused').withArgs(id) - - const registration = await registry.getUpkeep(id) - assert.equal(registration.paused, false) - - const upkeepIds = await registry.getActiveUpkeepIDs(0, 0) - assert.equal(upkeepIds.length, 1) - }) - }) - - describe('#updateCheckData', () => { - it('reverts if the caller is not upkeep admin', async () => { - await evmRevert( - registry.connect(keeper1).updateCheckData(id, randomBytes), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry.connect(admin).updateCheckData(id, randomBytes), - 'UpkeepCancelled()', - ) - }) - - it('updates the paused upkeep check data', async () => { - await registry.connect(admin).pauseUpkeep(id) - await registry.connect(admin).updateCheckData(id, randomBytes) - - const registration = await registry.getUpkeep(id) - assert.equal(randomBytes, registration.checkData) - }) - - it('updates the upkeep check data and emits an event', async () => { - const tx = await registry.connect(admin).updateCheckData(id, randomBytes) - await expect(tx) - .to.emit(registry, 'UpkeepCheckDataUpdated') - .withArgs(id, randomBytes) - - const registration = await registry.getUpkeep(id) - assert.equal(randomBytes, registration.checkData) - }) - }) - - describe('#registerUpkeep', () => { - context('and the registry is paused', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - it('reverts', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - zeroAddress, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'Pausable: paused', - ) - }) - }) - - it('reverts if the target is not a contract', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - zeroAddress, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'NotAContract()', - ) - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry - .connect(keeper1) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ), - 'OnlyCallableByOwnerOrRegistrar()', - ) - }) - - it('reverts if execute gas is too low', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 2299, - await admin.getAddress(), - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('reverts if execute gas is too high', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 5000001, - await admin.getAddress(), - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('creates a record of the registration', async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - id = await getUpkeepID(tx) - await expect(tx) - .to.emit(registry, 'UpkeepRegistered') - .withArgs(id, executeGas, await admin.getAddress()) - const registration = await registry.getUpkeep(id) - assert.equal(mock.address, registration.target) - assert.equal(0, registration.balance.toNumber()) - assert.equal(emptyBytes, registration.checkData) - assert.equal(registration.paused, false) - assert(registration.maxValidBlocknumber.eq('0xffffffff')) - }) - }) - - describe('#addFunds', () => { - const amount = toWei('1') - - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - }) - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).addFunds(id.add(1), amount), - 'UpkeepCancelled()', - ) - }) - - it('adds to the balance of the registration', async () => { - await registry.connect(keeper1).addFunds(id, amount) - const registration = await registry.getUpkeep(id) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('emits a log', async () => { - const tx = await registry.connect(keeper1).addFunds(id, amount) - await expect(tx) - .to.emit(registry, 'FundsAdded') - .withArgs(id, await keeper1.getAddress(), amount) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).addFunds(id, amount), - 'UpkeepCancelled()', - ) - }) - }) - - describe('#setUpkeepGasLimit', () => { - const newGasLimit = BigNumber.from('500000') - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).setUpkeepGasLimit(id.add(1), newGasLimit), - 'UpkeepCancelled()', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).setUpkeepGasLimit(id, newGasLimit), - 'UpkeepCancelled()', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry.connect(owner).setUpkeepGasLimit(id, newGasLimit), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if new gas limit is out of bounds', async () => { - await evmRevert( - registry.connect(admin).setUpkeepGasLimit(id, BigNumber.from('100')), - 'GasLimitOutsideRange()', - ) - await evmRevert( - registry - .connect(admin) - .setUpkeepGasLimit(id, BigNumber.from('6000000')), - 'GasLimitOutsideRange()', - ) - }) - - it('updates the gas limit successfully', async () => { - const initialGasLimit = (await registry.getUpkeep(id)).executeGas - assert.equal(initialGasLimit, executeGas.toNumber()) - await registry.connect(admin).setUpkeepGasLimit(id, newGasLimit) - const updatedGasLimit = (await registry.getUpkeep(id)).executeGas - assert.equal(updatedGasLimit, newGasLimit.toNumber()) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepGasLimit(id, newGasLimit) - await expect(tx) - .to.emit(registry, 'UpkeepGasLimitSet') - .withArgs(id, newGasLimit) - }) - }) - - describe('#checkUpkeep', () => { - it('reverts if the upkeep is not funded', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'InsufficientFunds()', - ) - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - }) - - it('reverts if executed', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry.checkUpkeep(id, await keeper1.getAddress()), - 'OnlySimulatedBackend()', - ) - }) - - it('reverts if the specified keeper is not valid', async () => { - await mock.setCanPerform(true) - await mock.setCanCheck(true) - await evmRevert( - registry.checkUpkeep(id, await owner.getAddress()), - 'OnlySimulatedBackend()', - ) - }) - - context('and upkeep is not needed', () => { - beforeEach(async () => { - await mock.setCanCheck(false) - }) - - it('reverts', async () => { - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'UpkeepNotNeeded()', - ) - }) - }) - - context('and the upkeep check fails', () => { - beforeEach(async () => { - const reverter = await upkeepReverterFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - reverter.address, - 2500000, - await admin.getAddress(), - emptyBytes, - ) - id = await getUpkeepID(tx) - await linkToken - .connect(keeper1) - .approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - }) - - it('reverts', async () => { - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'TargetCheckReverted', - ) - }) - }) - - context('and upkeep check simulations succeeds', () => { - beforeEach(async () => { - await mock.setCanCheck(true) - await mock.setCanPerform(true) - }) - - it('reverts if the upkeep is paused', async () => { - await registry.connect(admin).pauseUpkeep(id) - - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'OnlyUnpausedUpkeep()', - ) - }) - - it('returns true with pricing info if the target can execute', async () => { - const newGasMultiplier = BigNumber.from(10) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: newGasMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const response = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()) - assert.isTrue(response.gasLimit.eq(executeGas)) - assert.isTrue(response.linkEth.eq(linkEth)) - assert.isTrue( - response.adjustedGasWei.eq(gasWei.mul(newGasMultiplier)), - ) - assert.isTrue( - response.maxLinkPayment.eq( - linkForGas(executeGas.toNumber()).mul(newGasMultiplier), - ), - ) - }) - - it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => { - await mock.setCheckGasToBurn(checkGasLimit) - const gas = checkGasLimit.add(CHECK_GAS_OVERHEAD) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress(), { - gasLimit: gas, - }) - }) - }) - }) - }) - - describe('#performUpkeep', () => { - let _lastKeeper = keeper1 - - async function getPerformPaymentAmount() { - _lastKeeper = _lastKeeper === keeper1 ? keeper2 : keeper1 - const before = ( - await registry.getKeeperInfo(await _lastKeeper.getAddress()) - ).balance - await registry.connect(_lastKeeper).performUpkeep(id, '0x') - const after = ( - await registry.getKeeperInfo(await _lastKeeper.getAddress()) - ).balance - const difference = after.sub(before) - return difference - } - - it('reverts if the registration is not funded', async () => { - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'InsufficientFunds()', - ) - }) - - context('and the registry is paused', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts', async () => { - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'Pausable: paused', - ) - }) - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - }) - - it('does not revert if the target cannot execute', async () => { - const mockResponse = await mock - .connect(zeroAddress) - .callStatic.checkUpkeep('0x') - assert.isFalse(mockResponse.callable) - - await registry.connect(keeper3).performUpkeep(id, '0x') - }) - - it('returns false if the target cannot execute', async () => { - const mockResponse = await mock - .connect(zeroAddress) - .callStatic.checkUpkeep('0x') - assert.isFalse(mockResponse.callable) - - assert.isFalse( - await registry.connect(keeper1).callStatic.performUpkeep(id, '0x'), - ) - }) - - it('returns true if called', async () => { - await mock.setCanPerform(true) - - const response = await registry - .connect(keeper1) - .callStatic.performUpkeep(id, '0x') - assert.isTrue(response) - }) - - it('reverts if not enough gas supplied', async () => { - await mock.setCanPerform(true) - - await evmRevert( - registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasLimit: BigNumber.from('120000') }), - ) - }) - - it('executes the data passed to the registry', async () => { - await mock.setCanPerform(true) - - const performData = '0xc0ffeec0ffee' - const tx = await registry - .connect(keeper1) - .performUpkeep(id, performData, { gasLimit: extraGas }) - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 2) - assert.equal(eventLog?.[1].event, 'UpkeepPerformed') - expect(eventLog?.[1].args?.[0]).to.equal(id) - assert.equal(eventLog?.[1].args?.[1], true) - assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress()) - assert.isNotEmpty(eventLog?.[1].args?.[3]) - assert.equal(eventLog?.[1].args?.[4], performData) - }) - - it('updates payment balances', async () => { - const keeperBefore = await registry.getKeeperInfo( - await keeper1.getAddress(), - ) - const registrationBefore = await registry.getUpkeep(id) - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const keeperAfter = await registry.getKeeperInfo( - await keeper1.getAddress(), - ) - const registrationAfter = await registry.getUpkeep(id) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(keeperAfter.balance.gt(keeperBefore.balance)) - assert.isTrue(registrationBefore.balance.gt(registrationAfter.balance)) - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - }) - - it('updates amount spent correctly', async () => { - const registrationBefore = await registry.getUpkeep(id) - const balanceBefore = registrationBefore.balance - const amountSpentBefore = registrationBefore.amountSpent - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const registrationAfter = await registry.getUpkeep(id) - const balanceAfter = registrationAfter.balance - const amountSpentAfter = registrationAfter.amountSpent - - assert.isTrue(balanceAfter.lt(balanceBefore)) - assert.isTrue(amountSpentAfter.gt(amountSpentBefore)) - assert.isTrue( - amountSpentAfter - .sub(amountSpentBefore) - .eq(balanceBefore.sub(balanceAfter)), - ) - }) - - it('only pays for gas used [ @skip-coverage ]', async () => { - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry.connect(keeper1).performUpkeep(id, '0x') - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas.toNumber()) - const totalTx = linkForGas(receipt.gasUsed.toNumber()) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).lt(difference)) // exact number is flaky - assert.isTrue(linkForGas(6000).gt(difference)) // instead test a range - }) - - it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => { - const multiplier = BigNumber.from(10) - const gasPrice = BigNumber.from('1000000000') // 10M x the gas feed's rate - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasPrice }) - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas).mul(multiplier) - const totalTx = linkForGas(receipt.gasUsed).mul(multiplier) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).mul(multiplier).lt(difference)) - assert.isTrue(linkForGas(6000).mul(multiplier).gt(difference)) - }) - - it('only pays as much as the node spent [ @skip-coverage ]', async () => { - const multiplier = BigNumber.from(10) - const gasPrice = BigNumber.from(200) // 2X the gas feed's rate - const effectiveMultiplier = BigNumber.from(2) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const before = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(keeper1) - .performUpkeep(id, '0x', { gasPrice }) - const receipt = await tx.wait() - const after = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - - const max = linkForGas(executeGas.toNumber()).mul(effectiveMultiplier) - const totalTx = linkForGas(receipt.gasUsed).mul(effectiveMultiplier) - const difference = after.sub(before) - assert.isTrue(max.gt(totalTx)) - assert.isTrue(totalTx.gt(difference)) - assert.isTrue(linkForGas(5700).mul(effectiveMultiplier).lt(difference)) - assert.isTrue(linkForGas(6000).mul(effectiveMultiplier).gt(difference)) - }) - - it('pays the caller even if the target function fails', async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id = await getUpkeepID(tx) - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - const keeperBalanceBefore = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - - // Do the thing - await registry.connect(keeper1).performUpkeep(id, '0x') - - const keeperBalanceAfter = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - assert.isTrue(keeperBalanceAfter.gt(keeperBalanceBefore)) - }) - - it('reverts if called by a non-keeper', async () => { - await evmRevert( - registry.connect(nonkeeper).performUpkeep(id, '0x'), - 'OnlyActiveKeepers()', - ) - }) - - it('reverts if the upkeep has been canceled', async () => { - await mock.setCanPerform(true) - - await registry.connect(owner).cancelUpkeep(id) - - await evmRevert( - registry.connect(keeper1).performUpkeep(id, '0x'), - 'UpkeepCancelled()', - ) - }) - - it('reverts if the upkeep is paused', async () => { - await registry.connect(admin).pauseUpkeep(id) - - await evmRevert( - registry.connect(keeper1).performUpkeep(id, '0x'), - 'OnlyUnpausedUpkeep()', - ) - }) - - it('uses the fallback gas price if the feed price is stale [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const answer = 100 - const updatedAt = 946684800 // New Years 2000 🥳 - const startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - const amountWithStaleFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithStaleFeed)) - }) - - it('uses the fallback gas price if the feed price is non-sensical [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const updatedAt = Math.floor(Date.now() / 1000) - const startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - const amountWithNegativeFeed = await getPerformPaymentAmount() - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - const amountWithZeroFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithNegativeFeed)) - assert.isTrue(normalAmount.lt(amountWithZeroFeed)) - }) - - it('uses the fallback if the link price feed is stale', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const answer = 100 - const updatedAt = 946684800 // New Years 2000 🥳 - const startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - const amountWithStaleFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithStaleFeed)) - }) - - it('uses the fallback link price if the feed price is non-sensical [ @skip-coverage ]', async () => { - const normalAmount = await getPerformPaymentAmount() - const roundId = 99 - const updatedAt = Math.floor(Date.now() / 1000) - const startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - const amountWithNegativeFeed = await getPerformPaymentAmount() - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - const amountWithZeroFeed = await getPerformPaymentAmount() - assert.isTrue(normalAmount.lt(amountWithNegativeFeed)) - assert.isTrue(normalAmount.lt(amountWithZeroFeed)) - }) - - it('reverts if the same caller calls twice in a row', async () => { - await registry.connect(keeper1).performUpkeep(id, '0x') - await evmRevert( - registry.connect(keeper1).performUpkeep(id, '0x'), - 'KeepersMustTakeTurns()', - ) - await registry.connect(keeper2).performUpkeep(id, '0x') - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'KeepersMustTakeTurns()', - ) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => { - await registry.connect(admin).setUpkeepGasLimit(id, maxPerformGas) - await mock.setPerformGasToBurn(maxPerformGas) - await mock.setCanPerform(true) - const gas = maxPerformGas.add(PERFORM_GAS_OVERHEAD) - const performData = '0xc0ffeec0ffee' - const tx = await registry - .connect(keeper1) - .performUpkeep(id, performData, { gasLimit: gas }) - const receipt = await tx.wait() - const eventLog = receipt?.events - - assert.equal(eventLog?.length, 2) - assert.equal(eventLog?.[1].event, 'UpkeepPerformed') - expect(eventLog?.[1].args?.[0]).to.equal(id) - assert.equal(eventLog?.[1].args?.[1], true) - assert.equal(eventLog?.[1].args?.[2], await keeper1.getAddress()) - assert.isNotEmpty(eventLog?.[1].args?.[3]) - assert.equal(eventLog?.[1].args?.[4], performData) - }) - - it('can self fund', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - emptyBytes, - ) - const upkeepID = await getUpkeepID(tx) - await autoFunderUpkeep.setUpkeepId(upkeepID) - // Give enough funds for upkeep as well as to the upkeep contract - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - await linkToken - .connect(owner) - .transfer(autoFunderUpkeep.address, toWei('1000')) - let maxPayment = await registry.getMaxPaymentForGas(executeGas) - - // First set auto funding amount to 0 and verify that balance is deducted upon performUpkeep - let initialBalance = toWei('100') - await registry.connect(owner).addFunds(upkeepID, initialBalance) - await autoFunderUpkeep.setAutoFundLink(0) - await autoFunderUpkeep.setIsEligible(true) - await registry.connect(keeper1).performUpkeep(upkeepID, '0x') - - let postUpkeepBalance = (await registry.getUpkeep(upkeepID)).balance - assert.isTrue(postUpkeepBalance.lt(initialBalance)) // Balance should be deducted - assert.isTrue(postUpkeepBalance.gte(initialBalance.sub(maxPayment))) // Balance should not be deducted more than maxPayment - - // Now set auto funding amount to 100 wei and verify that the balance increases - initialBalance = postUpkeepBalance - let autoTopupAmount = toWei('100') - await autoFunderUpkeep.setAutoFundLink(autoTopupAmount) - await autoFunderUpkeep.setIsEligible(true) - await registry.connect(keeper2).performUpkeep(upkeepID, '0x') - - postUpkeepBalance = (await registry.getUpkeep(upkeepID)).balance - // Balance should increase by autoTopupAmount and decrease by max maxPayment - assert.isTrue( - postUpkeepBalance.gte( - initialBalance.add(autoTopupAmount).sub(maxPayment), - ), - ) - }) - - it('can self cancel', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - emptyBytes, - ) - const upkeepID = await getUpkeepID(tx) - await autoFunderUpkeep.setUpkeepId(upkeepID) - - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - await registry.connect(owner).addFunds(upkeepID, toWei('100')) - await autoFunderUpkeep.setIsEligible(true) - await autoFunderUpkeep.setShouldCancel(true) - - let registration = await registry.getUpkeep(upkeepID) - const oldExpiration = registration.maxValidBlocknumber - - // Do the thing - await registry.connect(keeper1).performUpkeep(upkeepID, '0x') - - // Verify upkeep gets cancelled - registration = await registry.getUpkeep(upkeepID) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - }) - }) - - describe('#withdrawFunds', () => { - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry - .connect(owner) - .withdrawFunds(id.add(1), await payee1.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if called on an uncanceled upkeep', async () => { - await evmRevert( - registry.connect(admin).withdrawFunds(id, await payee1.getAddress()), - 'UpkeepNotCanceled()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry.connect(admin).withdrawFunds(id, zeroAddress), - 'InvalidRecipient()', - ) - }) - - describe('after the registration is cancelled', () => { - beforeEach(async () => { - await registry.connect(owner).cancelUpkeep(id) - }) - - it('moves the funds out and updates the balance and emits an event', async () => { - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const registryBefore = await linkToken.balanceOf(registry.address) - - let registration = await registry.getUpkeep(id) - let previousBalance = registration.balance - - const tx = await registry - .connect(admin) - .withdrawFunds(id, await payee1.getAddress()) - await expect(tx) - .to.emit(registry, 'FundsWithdrawn') - .withArgs(id, previousBalance, await payee1.getAddress()) - - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - const registryAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(payee1Before.add(previousBalance).eq(payee1After)) - assert.isTrue(registryBefore.sub(previousBalance).eq(registryAfter)) - - registration = await registry.getUpkeep(id) - assert.equal(0, registration.balance.toNumber()) - }) - }) - }) - - describe('#withdrawOwnerFunds', () => { - it('can only be called by owner', async () => { - await evmRevert( - registry.connect(keeper1).withdrawOwnerFunds(), - 'Only callable by owner', - ) - }) - - it('withdraws the collected fees to owner', async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await registry.connect(keeper1).addFunds(id, toWei('100')) - // Very high min spend, whole balance as cancellation fees - let minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - let upkeepBalance = (await registry.getUpkeep(id)).balance - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).cancelUpkeep(id) - await registry.connect(admin).withdrawFunds(id, await payee1.getAddress()) - // Transfered to owner balance on registry - let ownerRegistryBalance = (await registry.getState()).state - .ownerLinkBalance - assert.isTrue(ownerRegistryBalance.eq(upkeepBalance)) - - // Now withdraw - await registry.connect(owner).withdrawOwnerFunds() - - ownerRegistryBalance = (await registry.getState()).state.ownerLinkBalance - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - // Owner registry balance should be changed to 0 - assert.isTrue(ownerRegistryBalance.eq(BigNumber.from('0'))) - - // Owner should be credited with the balance - assert.isTrue(ownerBefore.add(upkeepBalance).eq(ownerAfter)) - }) - }) - - describe('#cancelUpkeep', () => { - it('reverts if the ID is not valid', async () => { - await evmRevert( - registry.connect(owner).cancelUpkeep(id.add(1)), - 'CannotCancel()', - ) - }) - - it('reverts if called by a non-owner/non-admin', async () => { - await evmRevert( - registry.connect(keeper1).cancelUpkeep(id), - 'OnlyCallableByOwnerOrAdmin()', - ) - }) - - describe('when called by the owner', async () => { - it('sets the registration to invalid immediately', async () => { - const tx = await registry.connect(owner).cancelUpkeep(id) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(id) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).cancelUpkeep(id) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(id, BigNumber.from(receipt.blockNumber)) - }) - - it('immediately prevents upkeep', async () => { - await registry.connect(owner).cancelUpkeep(id) - - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'UpkeepCancelled()', - ) - }) - - it('does not revert if reverts if called multiple times', async () => { - await registry.connect(owner).cancelUpkeep(id) - await evmRevert( - registry.connect(owner).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - - describe('when called by the owner when the admin has just canceled', () => { - let oldExpiration: BigNumber - - beforeEach(async () => { - await registry.connect(admin).cancelUpkeep(id) - const registration = await registry.getUpkeep(id) - oldExpiration = registration.maxValidBlocknumber - }) - - it('allows the owner to cancel it more quickly', async () => { - await registry.connect(owner).cancelUpkeep(id) - - const registration = await registry.getUpkeep(id) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - }) - }) - - describe('when called by the admin', async () => { - const delay = 50 - - it('reverts if called again by the admin', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry.connect(admin).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - - it('reverts if called by the owner after the timeout', async () => { - await registry.connect(admin).cancelUpkeep(id) - - for (let i = 0; i < delay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevert( - registry.connect(owner).cancelUpkeep(id), - 'CannotCancel()', - ) - }) - - it('sets the registration to invalid in 50 blocks', async () => { - const tx = await registry.connect(admin).cancelUpkeep(id) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(id) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber + 50, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(admin).cancelUpkeep(id) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(id, BigNumber.from(receipt.blockNumber + delay)) - }) - - it('immediately prevents upkeep', async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.connect(admin).cancelUpkeep(id) - await registry.connect(keeper2).performUpkeep(id, '0x') // still works - - for (let i = 0; i < delay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevert( - registry.connect(keeper2).performUpkeep(id, '0x'), - 'UpkeepCancelled()', - ) - }) - - describe('when an upkeep has been performed', async () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('deducts a cancellation fee from the upkeep and gives to owner', async () => { - let minUpkeepSpend = toWei('10') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - let amountSpent = toWei('100').sub(upkeepBefore) - let cancellationFee = minUpkeepSpend.sub(amountSpent) - - await registry.connect(admin).cancelUpkeep(id) - - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepAfter = (await registry.getUpkeep(id)).balance - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // post upkeep balance should be previous balance minus cancellation fee - assert.isTrue(upkeepBefore.sub(cancellationFee).eq(upkeepAfter)) - // payee balance should not change - assert.isTrue(payee1Before.eq(payee1After)) - // owner should receive the cancellation fee - assert.isTrue(ownerAfter.eq(cancellationFee)) - }) - - it('deducts up to balance as cancellation fee', async () => { - // Very high min spend, should deduct whole balance as cancellation fees - let minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - await registry.connect(admin).cancelUpkeep(id) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - let upkeepAfter = (await registry.getUpkeep(id)).balance - - // all upkeep balance is deducted for cancellation fee - assert.equal(0, upkeepAfter.toNumber()) - // payee balance should not change - assert.isTrue(payee1After.eq(payee1Before)) - // all upkeep balance is transferred to the owner - assert.isTrue(ownerAfter.eq(upkeepBefore)) - }) - - it('does not deduct cancellation fee if more than minUpkeepSpend is spent', async () => { - // Very low min spend, already spent in one perform upkeep - let minUpkeepSpend = BigNumber.from(420) - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let upkeepBefore = (await registry.getUpkeep(id)).balance - let ownerBefore = (await registry.getState()).state.ownerLinkBalance - assert.equal(0, ownerBefore.toNumber()) - - await registry.connect(admin).cancelUpkeep(id) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - let ownerAfter = (await registry.getState()).state.ownerLinkBalance - let upkeepAfter = (await registry.getUpkeep(id)).balance - - // upkeep does not pay cancellation fee after cancellation because minimum upkeep spent is met - assert.isTrue(upkeepBefore.eq(upkeepAfter)) - // owner balance does not change - assert.equal(0, ownerAfter.toNumber()) - // payee balance does not change - assert.isTrue(payee1Before.eq(payee1After)) - }) - }) - }) - }) - - describe('#withdrawPayment', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.connect(keeper1).performUpkeep(id, '0x') - }) - - it('reverts if called by anyone but the payee', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment(await keeper1.getAddress(), zeroAddress), - 'InvalidRecipient()', - ) - }) - - it('updates the balances', async () => { - const to = await nonkeeper.getAddress() - const keeperBefore = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const registrationBefore = (await registry.getUpkeep(id)).balance - const toLinkBefore = await linkToken.balanceOf(to) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - - //// Do the thing - await registry - .connect(payee1) - .withdrawPayment(await keeper1.getAddress(), to) - - const keeperAfter = ( - await registry.getKeeperInfo(await keeper1.getAddress()) - ).balance - const registrationAfter = (await registry.getUpkeep(id)).balance - const toLinkAfter = await linkToken.balanceOf(to) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(keeperAfter.eq(BigNumber.from(0))) - assert.isTrue(registrationBefore.eq(registrationAfter)) - assert.isTrue(toLinkBefore.add(keeperBefore).eq(toLinkAfter)) - assert.isTrue(registryLinkBefore.sub(keeperBefore).eq(registryLinkAfter)) - }) - - it('emits a log announcing the withdrawal', async () => { - const balance = (await registry.getKeeperInfo(await keeper1.getAddress())) - .balance - const tx = await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PaymentWithdrawn') - .withArgs( - await keeper1.getAddress(), - balance, - await nonkeeper.getAddress(), - await payee1.getAddress(), - ) - }) - }) - - describe('#transferPayeeship', () => { - it('reverts when called by anyone but the current payee', async () => { - await evmRevert( - registry - .connect(payee2) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevert( - registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee1.getAddress(), - ), - 'ValueNotChanged()', - ) - }) - - it('does not change the payee', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const info = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.equal(await payee1.getAddress(), info.payee) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferRequested') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does not emit an event when called with the same proposal', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptPayeeship', () => { - beforeEach(async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('reverts when called by anyone but the proposed payee', async () => { - await evmRevert( - registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()), - 'OnlyCallableByProposedPayee()', - ) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee2) - .acceptPayeeship(await keeper1.getAddress()) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferred') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does change the payee', async () => { - await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress()) - - const info = await registry.getKeeperInfo(await keeper1.getAddress()) - assert.equal(await payee2.getAddress(), info.payee) - }) - }) - - describe('#transferUpkeepAdmin', () => { - beforeEach(async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - id = await getUpkeepID(tx) - }) - - it('reverts when called by anyone but the current upkeep admin', async () => { - await evmRevert( - registry - .connect(payee1) - .transferUpkeepAdmin(id, await payee2.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(id, await admin.getAddress()), - 'ValueNotChanged()', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(id, await keeper1.getAddress()), - 'UpkeepCancelled()', - ) - }) - - it('reverts when transferring to zero address', async () => { - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(id, ethers.constants.AddressZero), - 'InvalidRecipient()', - ) - }) - - it('does not change the upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - - const upkeep = await registry.getUpkeep(id) - assert.equal(await admin.getAddress(), upkeep.admin) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferRequested') - .withArgs(id, await admin.getAddress(), await payee1.getAddress()) - }) - - it('does not emit an event when called with the same proposed upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptUpkeepAdmin', () => { - beforeEach(async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - }) - - it('reverts when not called by the proposed upkeep admin', async () => { - await evmRevert( - registry.connect(payee2).acceptUpkeepAdmin(id), - 'OnlyCallableByProposedAdmin()', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(id) - - await evmRevert( - registry.connect(payee1).acceptUpkeepAdmin(id), - 'UpkeepCancelled()', - ) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry.connect(payee1).acceptUpkeepAdmin(id) - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferred') - .withArgs(id, await admin.getAddress(), await payee1.getAddress()) - }) - - it('does change the payee', async () => { - await registry.connect(payee1).acceptUpkeepAdmin(id) - - const upkeep = await registry.getUpkeep(id) - assert.equal(await payee1.getAddress(), upkeep.admin) - }) - }) - - describe('#setConfig', () => { - const payment = BigNumber.from(1) - const flatFee = BigNumber.from(2) - const checks = BigNumber.from(3) - const staleness = BigNumber.from(4) - const ceiling = BigNumber.from(5) - const maxGas = BigNumber.from(6) - const fbGasEth = BigNumber.from(7) - const fbLinkEth = BigNumber.from(8) - - it('reverts when called by anyone but the proposed owner', async () => { - await evmRevert( - registry.connect(payee1).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - 'Only callable by owner', - ) - }) - - it('updates the config', async () => { - const old = (await registry.getState()).config - assert.isTrue(paymentPremiumPPB.eq(old.paymentPremiumPPB)) - assert.isTrue(flatFeeMicroLink.eq(old.flatFeeMicroLink)) - assert.isTrue(blockCountPerTurn.eq(old.blockCountPerTurn)) - assert.isTrue(stalenessSeconds.eq(old.stalenessSeconds)) - assert.isTrue(gasCeilingMultiplier.eq(old.gasCeilingMultiplier)) - - await registry.connect(owner).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - - const updated = (await registry.getState()).config - assert.equal(updated.paymentPremiumPPB, payment.toNumber()) - assert.equal(updated.flatFeeMicroLink, flatFee.toNumber()) - assert.equal(updated.blockCountPerTurn, checks.toNumber()) - assert.equal(updated.stalenessSeconds, staleness.toNumber()) - assert.equal(updated.gasCeilingMultiplier, ceiling.toNumber()) - assert.equal(updated.checkGasLimit, maxGas.toNumber()) - assert.equal(updated.fallbackGasPrice.toNumber(), fbGasEth.toNumber()) - assert.equal(updated.fallbackLinkPrice.toNumber(), fbLinkEth.toNumber()) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).setConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - blockCountPerTurn: checks, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - await expect(tx) - .to.emit(registry, 'ConfigSet') - .withArgs([ - payment, - flatFee, - checks, - maxGas, - staleness, - ceiling, - minUpkeepSpend, - maxPerformGas, - fbGasEth, - fbLinkEth, - ]) - }) - }) - - describe('#onTokenTransfer', () => { - const amount = toWei('1') - - it('reverts if not called by the LINK token', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id]) - - await evmRevert( - registry - .connect(keeper1) - .onTokenTransfer(await keeper1.getAddress(), amount, data), - 'OnlyCallableByLINKToken()', - ) - }) - - it('reverts if not called with more or less than 32 bytes', async () => { - const longData = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256'], - ['33', '34'], - ) - const shortData = '0x12345678' - - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, longData), - ) - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, shortData), - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(id) - await evmRevert( - registry.connect(keeper1).addFunds(id, amount), - 'UpkeepCancelled()', - ) - }) - - it('updates the funds of the job id passed', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id]) - - const before = (await registry.getUpkeep(id)).balance - await linkToken - .connect(owner) - .transferAndCall(registry.address, amount, data) - const after = (await registry.getUpkeep(id)).balance - - assert.isTrue(before.add(amount).eq(after)) - }) - }) - - describe('#recoverFunds', () => { - const sent = toWei('7') - - beforeEach(async () => { - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - - // add funds to upkeep 1 and perform and withdraw some payment - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id1 = await getUpkeepID(tx) - await registry.connect(keeper1).addFunds(id1, toWei('5')) - await registry.connect(keeper1).performUpkeep(id1, '0x') - await registry.connect(keeper2).performUpkeep(id1, '0x') - await registry.connect(keeper3).performUpkeep(id1, '0x') - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds directly to the registry - await linkToken.connect(keeper1).transfer(registry.address, sent) - - // add funds to upkeep 2 and perform and withdraw some payment - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const id2 = await getUpkeepID(tx2) - await registry.connect(keeper1).addFunds(id2, toWei('5')) - await registry.connect(keeper1).performUpkeep(id2, '0x') - await registry.connect(keeper2).performUpkeep(id2, '0x') - await registry.connect(keeper3).performUpkeep(id2, '0x') - await registry - .connect(payee2) - .withdrawPayment( - await keeper2.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds using onTokenTransfer - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id2]) - await linkToken - .connect(owner) - .transferAndCall(registry.address, toWei('1'), data) - - // remove a keeper - await registry - .connect(owner) - .setKeepers( - [await keeper1.getAddress(), await keeper2.getAddress()], - [await payee1.getAddress(), await payee2.getAddress()], - ) - - // withdraw some funds - await registry.connect(owner).cancelUpkeep(id1) - await registry.connect(admin).withdrawFunds(id1, await admin.getAddress()) - }) - - it('reverts if not called by owner', async () => { - await evmRevert( - registry.connect(keeper1).recoverFunds(), - 'Only callable by owner', - ) - }) - - it('allows any funds that have been accidentally transfered to be moved', async () => { - const balanceBefore = await linkToken.balanceOf(registry.address) - - await linkToken.balanceOf(registry.address) - - await registry.connect(owner).recoverFunds() - const balanceAfter = await linkToken.balanceOf(registry.address) - assert.isTrue(balanceBefore.eq(balanceAfter.add(sent))) - }) - }) - - describe('#pause', () => { - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).pause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse(await registry.paused()) - - await registry.connect(owner).pause() - - assert.isTrue(await registry.paused()) - }) - }) - - describe('#unpause', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).unpause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as not paused', async () => { - assert.isTrue(await registry.paused()) - - await registry.connect(owner).unpause() - - assert.isFalse(await registry.paused()) - }) - }) - - describe('#getMaxPaymentForGas', () => { - const gasAmounts = [100000, 10000000] - const premiums = [0, 250000000] - const flatFees = [0, 1000000] - it('calculates the max fee appropriately', async () => { - const registryLogicL1 = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - 0, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - await verifyMaxPayment(registryLogicL1, gasAmounts, premiums, flatFees) - }) - - it('calculates the max fee appropriately for Arbitrum', async () => { - const registryLogicArb = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - 1, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - await verifyMaxPayment( - registryLogicArb, - gasAmounts, - premiums, - flatFees, - l1CostWeiArb, - ) - }) - - it('calculates the max fee appropriately for Optimism', async () => { - const registryLogicOpt = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - 2, - registryGasOverhead, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - await verifyMaxPayment( - registryLogicOpt, - gasAmounts, - premiums, - flatFees, - l1CostWeiOpt, - ) - }) - }) - - describe('#setPeerRegistryMigrationPermission() / #getPeerRegistryMigrationPermission()', () => { - const peer = randomAddress() - it('allows the owner to set the peer registries', async () => { - let permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - await registry.setPeerRegistryMigrationPermission(peer, 1) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(1) - await registry.setPeerRegistryMigrationPermission(peer, 2) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(2) - await registry.setPeerRegistryMigrationPermission(peer, 0) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - }) - it('reverts if passed an unsupported permission', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 10), - ).to.be.reverted - }) - it('reverts if not called by the owner', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 1), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('migrateUpkeeps() / #receiveUpkeeps()', async () => { - context('when permissions are set', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(id, toWei('100')) - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - }) - - it('migrates an upkeep', async () => { - expect((await registry.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - await registry - .connect(admin) - .transferUpkeepAdmin(id, await payee1.getAddress()) - - // migrate - await registry.connect(admin).migrateUpkeeps([id], registry2.address) - expect((await registry.getState()).state.numUpkeeps).to.equal(0) - expect((await registry2.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(id)).balance).to.equal(0) - expect((await registry.getUpkeep(id)).checkData).to.equal('0x') - expect((await registry2.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry2.getState()).state.expectedLinkBalance).to.equal( - toWei('100'), - ) - expect((await registry2.getUpkeep(id)).checkData).to.equal(randomBytes) - // migration will delete the upkeep and nullify admin transfer - await expect( - registry.connect(payee1).acceptUpkeepAdmin(id), - ).to.be.revertedWith('UpkeepCancelled()') - await expect( - registry2.connect(payee1).acceptUpkeepAdmin(id), - ).to.be.revertedWith('OnlyCallableByProposedAdmin()') - }) - - it('migrates a paused upkeep', async () => { - expect((await registry.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - await registry.connect(admin).pauseUpkeep(id) - // verify the upkeep is paused - expect((await registry.getUpkeep(id)).paused).to.equal(true) - // migrate - await registry.connect(admin).migrateUpkeeps([id], registry2.address) - expect((await registry.getState()).state.numUpkeeps).to.equal(0) - expect((await registry2.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(id)).balance).to.equal(0) - expect((await registry2.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal('0x') - expect((await registry2.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry2.getState()).state.expectedLinkBalance).to.equal( - toWei('100'), - ) - // verify the upkeep is still paused after migration - expect((await registry2.getUpkeep(id)).paused).to.equal(true) - }) - - it('emits an event on both contracts', async () => { - expect((await registry.getUpkeep(id)).balance).to.equal(toWei('100')) - expect((await registry.getUpkeep(id)).checkData).to.equal(randomBytes) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - const tx = registry - .connect(admin) - .migrateUpkeeps([id], registry2.address) - await expect(tx) - .to.emit(registry, 'UpkeepMigrated') - .withArgs(id, toWei('100'), registry2.address) - await expect(tx) - .to.emit(registry2, 'UpkeepReceived') - .withArgs(id, toWei('100'), registry.address) - }) - it('is only migratable by the admin', async () => { - await expect( - registry.connect(owner).migrateUpkeeps([id], registry2.address), - ).to.be.revertedWith('OnlyCallableByAdmin()') - await registry.connect(admin).migrateUpkeeps([id], registry2.address) - }) - }) - - context('when permissions are not set', () => { - it('reverts', async () => { - // no permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // only outgoing permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // only incoming permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - // permissions opposite direction - await registry.setPeerRegistryMigrationPermission(registry2.address, 2) - await registry2.setPeerRegistryMigrationPermission(registry.address, 1) - await expect(registry.migrateUpkeeps([id], registry2.address)).to.be - .reverted - }) - }) - }) - - describe('#checkUpkeep / #performUpkeep', () => { - const performData = '0xc0ffeec0ffee' - const multiplier = BigNumber.from(10) - const flatFee = BigNumber.from('100000') //0.1 LINK - const callGasPrice = 1 - - it('uses the same minimum balance calculation [ @skip-coverage ]', async () => { - await registry.connect(owner).setConfig({ - paymentPremiumPPB, - flatFeeMicroLink: flatFee, - blockCountPerTurn, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }) - await linkToken.connect(owner).approve(registry.address, toWei('100')) - - const tx1 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const upkeepID1 = await getUpkeepID(tx1) - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - ) - const upkeepID2 = await getUpkeepID(tx2) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - // upkeep 1 is underfunded, 2 is funded - const minBalance1 = (await registry.getMaxPaymentForGas(executeGas)).sub( - 1, - ) - const minBalance2 = await registry.getMaxPaymentForGas(executeGas) - await registry.connect(owner).addFunds(upkeepID1, minBalance1) - await registry.connect(owner).addFunds(upkeepID2, minBalance2) - // upkeep 1 check should revert, 2 should succeed - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID1, await keeper1.getAddress(), { - gasPrice: callGasPrice, - }), - ) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID2, await keeper1.getAddress(), { - gasPrice: callGasPrice, - }) - // upkeep 1 perform should revert, 2 should succeed - await evmRevert( - registry - .connect(keeper1) - .performUpkeep(upkeepID1, performData, { gasLimit: extraGas }), - 'InsufficientFunds()', - ) - await registry - .connect(keeper1) - .performUpkeep(upkeepID2, performData, { gasLimit: extraGas }) - }) - }) - - describe('#getMinBalanceForUpkeep / #checkUpkeep', () => { - it('calculates the minimum balance appropriately', async () => { - const oneWei = BigNumber.from('1') - await linkToken.connect(keeper1).approve(registry.address, toWei('100')) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - const minBalance = await registry.getMinBalanceForUpkeep(id) - const tooLow = minBalance.sub(oneWei) - await registry.connect(keeper1).addFunds(id, tooLow) - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()), - 'InsufficientFunds()', - ) - await registry.connect(keeper1).addFunds(id, oneWei) - await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(id, await keeper1.getAddress()) - }) - }) -}) diff --git a/contracts/test/v0.8/automation/KeeperRegistry2_0.test.ts b/contracts/test/v0.8/automation/KeeperRegistry2_0.test.ts deleted file mode 100644 index 940d809c9d1..00000000000 --- a/contracts/test/v0.8/automation/KeeperRegistry2_0.test.ts +++ /dev/null @@ -1,4802 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { BigNumber, Signer, Wallet } from 'ethers' -import { evmRevert } from '../../test-helpers/matchers' -import { getUsers, Personas } from '../../test-helpers/setup' -import { toWei } from '../../test-helpers/helpers' -import { LinkToken__factory as LinkTokenFactory } from '../../../typechain/factories/LinkToken__factory' -import { MockV3Aggregator__factory as MockV3AggregatorFactory } from '../../../typechain/factories/MockV3Aggregator__factory' -import { UpkeepMock__factory as UpkeepMockFactory } from '../../../typechain/factories/UpkeepMock__factory' -import { UpkeepAutoFunder__factory as UpkeepAutoFunderFactory } from '../../../typechain/factories/UpkeepAutoFunder__factory' -import { UpkeepTranscoder__factory as UpkeepTranscoderFactory } from '../../../typechain/factories/UpkeepTranscoder__factory' -import { KeeperRegistry2_0__factory as KeeperRegistryFactory } from '../../../typechain/factories/KeeperRegistry2_0__factory' -import { MockArbGasInfo__factory as MockArbGasInfoFactory } from '../../../typechain/factories/MockArbGasInfo__factory' -import { MockOVMGasPriceOracle__factory as MockOVMGasPriceOracleFactory } from '../../../typechain/factories/MockOVMGasPriceOracle__factory' -import { KeeperRegistryLogic2_0__factory as KeeperRegistryLogicFactory } from '../../../typechain/factories/KeeperRegistryLogic2_0__factory' -import { MockArbSys__factory as MockArbSysFactory } from '../../../typechain/factories/MockArbSys__factory' -import { KeeperRegistry2_0 as KeeperRegistry } from '../../../typechain/KeeperRegistry2_0' -import { KeeperRegistryLogic20 as KeeperRegistryLogic } from '../../../typechain/KeeperRegistryLogic20' -import { MockV3Aggregator } from '../../../typechain/MockV3Aggregator' -import { LinkToken } from '../../../typechain/LinkToken' -import { UpkeepMock } from '../../../typechain/UpkeepMock' -import { MockArbGasInfo } from '../../../typechain/MockArbGasInfo' -import { MockOVMGasPriceOracle } from '../../../typechain/MockOVMGasPriceOracle' -import { UpkeepTranscoder } from '../../../typechain/UpkeepTranscoder' - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -/*********************************** REGISTRY v2.0 IS FROZEN ************************************/ - -// All tests are disabled for this contract, as we expect it to never change in the future. -// Instead, we test that the bytecode for the contract has not changed. -// If this test ever fails, you should remove it and then re-run the original test suite. - -const BYTECODE = KeeperRegistryFactory.bytecode -const BYTECODE_CHECKSUM = - '0x60660453a335cdcd42b5aa64e58a8c04517e8a8645d2618b51a7552df6e2973b' - -describe('KeeperRegistry2_0 - Frozen [ @skip-coverage ]', () => { - it('has not changed', () => { - assert.equal(ethers.utils.id(BYTECODE), BYTECODE_CHECKSUM) - }) -}) - -////////////////////////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////////////////////////// - -// copied from AutomationRegistryInterface2_0.sol -enum UpkeepFailureReason { - NONE, - UPKEEP_CANCELLED, - UPKEEP_PAUSED, - TARGET_CHECK_REVERTED, - UPKEEP_NOT_NEEDED, - PERFORM_DATA_EXCEEDS_LIMIT, - INSUFFICIENT_BALANCE, -} - -// copied from AutomationRegistryInterface2_0.sol -enum Mode { - DEFAULT, - ARBITRUM, - OPTIMISM, -} - -async function getUpkeepID(tx: any) { - const receipt = await tx.wait() - return receipt.events[0].args.id -} - -function randomAddress() { - return ethers.Wallet.createRandom().address -} - -// ----------------------------------------------------------------------------------------------- -// These are the gas overheads that off chain systems should provide to check upkeep / transmit -// These overheads are not actually charged for -const transmitGasOverhead = BigNumber.from(800000) -const checkGasOverhead = BigNumber.from(400000) - -// These values should match the constants declared in registry -const registryGasOverhead = BigNumber.from(70_000) -const registryPerSignerGasOverhead = BigNumber.from(7500) -const registryPerPerformByteGasOverhead = BigNumber.from(20) -const cancellationDelay = 50 - -// This is the margin for gas that we test for. Gas charged should always be greater -// than total gas used in tx but should not increase beyond this margin -const gasCalculationMargin = BigNumber.from(4000) -// ----------------------------------------------------------------------------------------------- - -// Smart contract factories -let linkTokenFactory: LinkTokenFactory -let mockV3AggregatorFactory: MockV3AggregatorFactory -let keeperRegistryFactory: KeeperRegistryFactory -let keeperRegistryLogicFactory: KeeperRegistryLogicFactory -let upkeepMockFactory: UpkeepMockFactory -let upkeepAutoFunderFactory: UpkeepAutoFunderFactory -let upkeepTranscoderFactory: UpkeepTranscoderFactory -let mockArbGasInfoFactory: MockArbGasInfoFactory -let mockOVMGasPriceOracleFactory: MockOVMGasPriceOracleFactory -let personas: Personas - -const encodeConfig = (config: any) => { - return ethers.utils.defaultAbiCoder.encode( - [ - 'tuple(uint32 paymentPremiumPPB,uint32 flatFeeMicroLink,uint32 checkGasLimit,uint24 stalenessSeconds\ - ,uint16 gasCeilingMultiplier,uint96 minUpkeepSpend,uint32 maxPerformGas,uint32 maxCheckDataSize,\ - uint32 maxPerformDataSize,uint256 fallbackGasPrice,uint256 fallbackLinkPrice,address transcoder,\ - address registrar)', - ], - [config], - ) -} - -const linkEth = BigNumber.from(5000000000000000) // 1 Link = 0.005 Eth -const gasWei = BigNumber.from(1000000000) // 1 gwei -const encodeReport = ( - upkeeps: any, - gasWeiReport = gasWei, - linkEthReport = linkEth, -) => { - const upkeepIds = upkeeps.map((u: any) => u.Id) - const performDataTuples = upkeeps.map((u: any) => [ - u.checkBlockNum, - u.checkBlockHash, - u.performData, - ]) - return ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256', 'uint256[]', 'tuple(uint32,bytes32,bytes)[]'], - [gasWeiReport, linkEthReport, upkeepIds, performDataTuples], - ) -} - -const encodeLatestBlockReport = async (upkeeps: any) => { - const latestBlock = await ethers.provider.getBlock('latest') - for (let i = 0; i < upkeeps.length; i++) { - upkeeps[i].checkBlockNum = latestBlock.number - upkeeps[i].checkBlockHash = latestBlock.hash - upkeeps[i].performData = '0x' - } - return encodeReport(upkeeps) -} - -const signReport = ( - reportContext: string[], - report: any, - signers: Wallet[], -) => { - const reportDigest = ethers.utils.keccak256(report) - const packedArgs = ethers.utils.solidityPack( - ['bytes32', 'bytes32[3]'], - [reportDigest, reportContext], - ) - const packedDigest = ethers.utils.keccak256(packedArgs) - - const signatures = [] - for (const signer of signers) { - signatures.push(signer._signingKey().signDigest(packedDigest)) - } - const vs = signatures.map((i) => '0' + (i.v - 27).toString(16)).join('') - return { - vs: '0x' + vs.padEnd(64, '0'), - rs: signatures.map((i) => i.r), - ss: signatures.map((i) => i.s), - } -} - -const parseUpkeepPerformedLogs = (receipt: any) => { - const upkeepPerformedABI = [ - 'event UpkeepPerformed(uint256 indexed id,bool indexed success, \ - uint32 checkBlockNumber,uint256 gasUsed,uint256 gasOverhead,uint96 totalPayment)', - ] - const iface = new ethers.utils.Interface(upkeepPerformedABI) - - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - return parsedLogs -} - -const parseReorgedUpkeepReportLogs = (receipt: any) => { - const logABI = [' event ReorgedUpkeepReport(uint256 indexed id)'] - const iface = new ethers.utils.Interface(logABI) - - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - return parsedLogs -} - -const parseStaleUpkeepReportLogs = (receipt: any) => { - const logABI = [' event StaleUpkeepReport(uint256 indexed id)'] - const iface = new ethers.utils.Interface(logABI) - - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - return parsedLogs -} - -const parseInsufficientFundsUpkeepReportLogs = (receipt: any) => { - const logABI = [' event InsufficientFundsUpkeepReport(uint256 indexed id)'] - const iface = new ethers.utils.Interface(logABI) - - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - return parsedLogs -} - -const parseCancelledUpkeepReportLogs = (receipt: any) => { - const logABI = [' event CancelledUpkeepReport(uint256 indexed id)'] - const iface = new ethers.utils.Interface(logABI) - - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - return parsedLogs -} - -before(async () => { - personas = (await getUsers()).personas - - linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/shared/test/helpers/LinkTokenTestHelper.sol:LinkTokenTestHelper', - ) - // need full path because there are two contracts with name MockV3Aggregator - mockV3AggregatorFactory = (await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - )) as unknown as MockV3AggregatorFactory - keeperRegistryFactory = (await ethers.getContractFactory( - 'KeeperRegistry2_0', - )) as unknown as KeeperRegistryFactory // bug in typechain requires force casting - keeperRegistryLogicFactory = (await ethers.getContractFactory( - 'KeeperRegistryLogic2_0', - )) as unknown as KeeperRegistryLogicFactory // bug in typechain requires force casting - upkeepMockFactory = await ethers.getContractFactory('UpkeepMock') - upkeepAutoFunderFactory = await ethers.getContractFactory('UpkeepAutoFunder') - upkeepTranscoderFactory = await ethers.getContractFactory('UpkeepTranscoder') - mockArbGasInfoFactory = await ethers.getContractFactory('MockArbGasInfo') - mockOVMGasPriceOracleFactory = await ethers.getContractFactory( - 'MockOVMGasPriceOracle', - ) -}) - -describe.skip('KeeperRegistry2_0', () => { - const linkDivisibility = BigNumber.from('1000000000000000000') - const executeGas = BigNumber.from('1000000') - const paymentPremiumBase = BigNumber.from('1000000000') - const paymentPremiumPPB = BigNumber.from('250000000') - const flatFeeMicroLink = BigNumber.from(0) - - const randomBytes = '0x1234abcd' - const emptyBytes = '0x' - const emptyBytes32 = - '0x0000000000000000000000000000000000000000000000000000000000000000' - - const stalenessSeconds = BigNumber.from(43820) - const gasCeilingMultiplier = BigNumber.from(2) - const checkGasLimit = BigNumber.from(10000000) - const fallbackGasPrice = gasWei.mul(BigNumber.from('2')) - const fallbackLinkPrice = linkEth.div(BigNumber.from('2')) - const maxCheckDataSize = BigNumber.from(1000) - const maxPerformDataSize = BigNumber.from(1000) - const maxPerformGas = BigNumber.from(5000000) - const minUpkeepSpend = BigNumber.from(0) - const f = 1 - const offchainVersion = 1 - const offchainBytes = '0x' - const zeroAddress = ethers.constants.AddressZero - const epochAndRound5_1 = - '0x0000000000000000000000000000000000000000000000000000000000000501' - - let owner: Signer - let keeper1: Signer - let keeper2: Signer - let keeper3: Signer - let keeper4: Signer - let keeper5: Signer - let nonkeeper: Signer - let signer1: Wallet - let signer2: Wallet - let signer3: Wallet - let signer4: Wallet - let signer5: Wallet - let admin: Signer - let payee1: Signer - let payee2: Signer - let payee3: Signer - let payee4: Signer - let payee5: Signer - - let linkToken: LinkToken - let linkEthFeed: MockV3Aggregator - let gasPriceFeed: MockV3Aggregator - let registry: KeeperRegistry - let registryLogic: KeeperRegistryLogic - let mock: UpkeepMock - let transcoder: UpkeepTranscoder - let mockArbGasInfo: MockArbGasInfo - let mockOVMGasPriceOracle: MockOVMGasPriceOracle - - let upkeepId: BigNumber - let keeperAddresses: string[] - let payees: string[] - let signers: Wallet[] - let signerAddresses: string[] - let config: any - - const linkForGas = ( - upkeepGasSpent: BigNumber, - gasOverhead: BigNumber, - gasMultiplier: BigNumber, - premiumPPB: BigNumber, - flatFee: BigNumber, - l1CostWei?: BigNumber, - numUpkeepsBatch?: BigNumber, - ) => { - l1CostWei = l1CostWei === undefined ? BigNumber.from(0) : l1CostWei - numUpkeepsBatch = - numUpkeepsBatch === undefined ? BigNumber.from(1) : numUpkeepsBatch - - const gasSpent = gasOverhead.add(BigNumber.from(upkeepGasSpent)) - const base = gasWei - .mul(gasMultiplier) - .mul(gasSpent) - .mul(linkDivisibility) - .div(linkEth) - const l1Fee = l1CostWei - .mul(gasMultiplier) - .div(numUpkeepsBatch) - .mul(linkDivisibility) - .div(linkEth) - const gasPayment = base.add(l1Fee) - - const premium = gasWei - .mul(gasMultiplier) - .mul(upkeepGasSpent) - .add(l1CostWei.mul(gasMultiplier).div(numUpkeepsBatch)) - .mul(linkDivisibility) - .div(linkEth) - .mul(premiumPPB) - .div(paymentPremiumBase) - .add(BigNumber.from(flatFee).mul('1000000000000')) - - return { - total: gasPayment.add(premium), - gasPaymemnt: gasPayment, - premium, - } - } - - const verifyMaxPayment = async ( - mode: number, - multipliers: BigNumber[], - gasAmounts: number[], - premiums: number[], - flatFees: number[], - l1CostWei?: BigNumber, - ) => { - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - - // Deploy a new registry since we change payment model - const registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - mode, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - // Deploy a new registry since we change payment model - const registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - - const fPlusOne = BigNumber.from(f + 1) - const totalGasOverhead = registryGasOverhead - .add(registryPerSignerGasOverhead.mul(fPlusOne)) - .add(registryPerPerformByteGasOverhead.mul(maxPerformDataSize)) - - for (let idx = 0; idx < gasAmounts.length; idx++) { - const gas = gasAmounts[idx] - for (let jdx = 0; jdx < premiums.length; jdx++) { - const premium = premiums[jdx] - for (let kdx = 0; kdx < flatFees.length; kdx++) { - const flatFee = flatFees[kdx] - for (let ldx = 0; ldx < multipliers.length; ldx++) { - const multiplier = multipliers[ldx] - - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: premium, - flatFeeMicroLink: flatFee, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier: multiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - - const price = await registry.getMaxPaymentForGas(gas) - expect(price).to.equal( - linkForGas( - BigNumber.from(gas), - totalGasOverhead, - multiplier, - BigNumber.from(premium), - BigNumber.from(flatFee), - l1CostWei, - ).total, - ) - } - } - } - } - } - - const getTransmitTx = async ( - registry: KeeperRegistry, - transmitter: any, - upkeepIds: any, - numSigners: any, - extraParams?: any, - performData?: any, - checkBlockNum?: any, - checkBlockHash?: any, - ) => { - const latestBlock = await ethers.provider.getBlock('latest') - const configDigest = (await registry.getState()).state.latestConfigDigest - - const upkeeps = [] - for (let i = 0; i < upkeepIds.length; i++) { - upkeeps.push({ - Id: upkeepIds[i], - checkBlockNum: checkBlockNum ? checkBlockNum : latestBlock.number, - checkBlockHash: checkBlockHash ? checkBlockHash : latestBlock.hash, - performData: performData ? performData : '0x', - }) - } - - const report = encodeReport(upkeeps) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] - const sigs = signReport(reportContext, report, signers.slice(0, numSigners)) - - return registry - .connect(transmitter) - .transmit( - [configDigest, epochAndRound5_1, emptyBytes32], - report, - sigs.rs, - sigs.ss, - sigs.vs, - { gasLimit: extraParams?.gasLimit, gasPrice: extraParams?.gasPrice }, - ) - } - - const getTransmitTxWithReport = async ( - registry: KeeperRegistry, - transmitter: any, - report: any, - numSigners: any, - ) => { - const configDigest = (await registry.getState()).state.latestConfigDigest - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] - const sigs = signReport(reportContext, report, signers.slice(0, numSigners)) - - return registry - .connect(transmitter) - .transmit( - [configDigest, epochAndRound5_1, emptyBytes32], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ) - } - - beforeEach(async () => { - // Deploys a registry, setups of initial configuration - // Registers an upkeep which is unfunded to start with - owner = personas.Default - keeper1 = personas.Carol - keeper2 = personas.Eddy - keeper3 = personas.Nancy - keeper4 = personas.Norbert - keeper5 = personas.Nick - nonkeeper = personas.Ned - admin = personas.Neil - payee1 = personas.Nelly - payee2 = personas.Norbert - payee3 = personas.Nick - payee4 = personas.Eddy - payee5 = personas.Carol - // signers - signer1 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000001', - ) - signer2 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000002', - ) - signer3 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000003', - ) - signer4 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000004', - ) - signer5 = new ethers.Wallet( - '0x7777777000000000000000000000000000000000000000000000000000000005', - ) - - keeperAddresses = [ - await keeper1.getAddress(), - await keeper2.getAddress(), - await keeper3.getAddress(), - await keeper4.getAddress(), - await keeper5.getAddress(), - ] - payees = [ - await payee1.getAddress(), - await payee2.getAddress(), - await payee3.getAddress(), - await payee4.getAddress(), - await payee5.getAddress(), - ] - signers = [signer1, signer2, signer3, signer4, signer5] - - // We append 26 random addresses to keepers, payees and signers to get a system of 31 oracles - // This allows f value of 1 - 10 - for (let i = 0; i < 26; i++) { - keeperAddresses.push(randomAddress()) - payees.push(randomAddress()) - signers.push(ethers.Wallet.createRandom()) - } - signerAddresses = [] - for (const signer of signers) { - signerAddresses.push(await signer.getAddress()) - } - - linkToken = await linkTokenFactory.connect(owner).deploy() - gasPriceFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(0, gasWei) - linkEthFeed = await mockV3AggregatorFactory - .connect(owner) - .deploy(9, linkEth) - transcoder = await upkeepTranscoderFactory.connect(owner).deploy() - mockArbGasInfo = await mockArbGasInfoFactory.connect(owner).deploy() - mockOVMGasPriceOracle = await mockOVMGasPriceOracleFactory - .connect(owner) - .deploy() - - const arbOracleCode = await ethers.provider.send('eth_getCode', [ - mockArbGasInfo.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x000000000000000000000000000000000000006C', - arbOracleCode, - ]) - - const optOracleCode = await ethers.provider.send('eth_getCode', [ - mockOVMGasPriceOracle.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x420000000000000000000000000000000000000F', - optOracleCode, - ]) - - const mockArbSys = await new MockArbSysFactory(owner).deploy() - const arbSysCode = await ethers.provider.send('eth_getCode', [ - mockArbSys.address, - ]) - await ethers.provider.send('hardhat_setCode', [ - '0x0000000000000000000000000000000000000064', - arbSysCode, - ]) - - registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - Mode.DEFAULT, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - await registry.connect(owner).setPayees(payees) - - mock = await upkeepMockFactory.deploy() - await linkToken - .connect(owner) - .transfer(await admin.getAddress(), toWei('1000')) - await linkToken.connect(admin).approve(registry.address, toWei('1000')) - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - }) - - describe('#transmit', () => { - const fArray = [1, 5, 10] - - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevert( - getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1), - 'RegistryPaused()', - ) - }) - - it('reverts when called by non active transmitter', async () => { - await evmRevert( - getTransmitTx(registry, payee1, [upkeepId.toString()], f + 1), - 'OnlyActiveTransmitters()', - ) - }) - - it('reverts when upkeeps and performData length mismatches', async () => { - const upkeepIds = [] - const performDataTuples = [] - const latestBlock = await ethers.provider.getBlock('latest') - - upkeepIds.push(upkeepId) - performDataTuples.push([latestBlock.number + 1, latestBlock.hash, '0x']) - // Push an extra perform data - performDataTuples.push([latestBlock.number + 1, latestBlock.hash, '0x']) - - const report = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256', 'uint256[]', 'tuple(uint32,bytes32,bytes)[]'], - [0, 0, upkeepIds, performDataTuples], - ) - - await evmRevert( - getTransmitTxWithReport(registry, keeper1, report, f + 1), - 'InvalidReport()', - ) - }) - - it('reverts when wrappedPerformData is incorrectly encoded', async () => { - const upkeepIds = [] - const wrappedPerformDatas = [] - const latestBlock = await ethers.provider.getBlock('latest') - - upkeepIds.push(upkeepId) - wrappedPerformDatas.push( - ethers.utils.defaultAbiCoder.encode( - ['tuple(uint32,bytes32)'], // missing performData - [[latestBlock.number + 1, latestBlock.hash]], - ), - ) - - const report = ethers.utils.defaultAbiCoder.encode( - ['uint256[]', 'bytes[]'], - [upkeepIds, wrappedPerformDatas], - ) - - await evmRevert(getTransmitTxWithReport(registry, keeper1, report, f + 1)) - }) - - it('returns early when no upkeeps are included in report', async () => { - const upkeepIds: string[] = [] - const wrappedPerformDatas: string[] = [] - const report = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256', 'uint256[]', 'bytes[]'], - [0, 0, upkeepIds, wrappedPerformDatas], - ) - - await getTransmitTxWithReport(registry, keeper1, report, f + 1) - }) - - it('returns early when invalid upkeepIds are included in report', async () => { - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.add(BigNumber.from('1')).toString()], - f + 1, - ) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('reverts when duplicated upkeepIds are included in report', async () => { - // Fund the upkeep so that pre-checks pass - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - await evmRevert( - getTransmitTx( - registry, - keeper1, - [upkeepId.toString(), upkeepId.toString()], - f + 1, - ), - 'InvalidReport()', - ) - }) - - it('returns early when upkeep has insufficient funds', async () => { - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - - const receipt = await tx.wait() - const insufficientFundsUpkeepReportLogs = - parseInsufficientFundsUpkeepReportLogs(receipt) - // exactly 1 InsufficientFundsUpkeepReportLogs log should be emitted - assert.equal(insufficientFundsUpkeepReportLogs.length, 1) - }) - - context('When the upkeep is funded', async () => { - beforeEach(async () => { - // Fund the upkeep - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - }) - - it('returns early when check block number is less than last perform', async () => { - // First perform an upkeep to put last perform block number on upkeep state - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - await tx.wait() - - const lastPerformBlockNumber = (await registry.getUpkeep(upkeepId)) - .lastPerformBlockNumber - const lastPerformBlock = await ethers.provider.getBlock( - lastPerformBlockNumber, - ) - assert.equal( - lastPerformBlockNumber.toString(), - tx.blockNumber?.toString(), - ) - - // Try to transmit a report which has checkBlockNumber = lastPerformBlockNumber-1, should result in stale report - const transmitTx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - {}, - '0x', - lastPerformBlock.number - 1, - lastPerformBlock.parentHash, - ) - - const receipt = await transmitTx.wait() - const staleUpkeepReportLogs = parseStaleUpkeepReportLogs(receipt) - // exactly 1 StaleUpkeepReportLogs log should be emitted - assert.equal(staleUpkeepReportLogs.length, 1) - }) - - it('returns early when check block hash does not match', async () => { - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - const latestBlock = await ethers.provider.getBlock('latest') - // Try to transmit a report which has incorrect checkBlockHash - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - {}, - '0x', - latestBlock.number - 1, - latestBlock.hash, - ) // should be latestBlock.parentHash - - const receipt = await tx.wait() - const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal(reorgedUpkeepReportLogs.length, 1) - }) - - it('returns early when check block number is older than 256 blocks', async () => { - const latestBlockReport = await encodeLatestBlockReport([ - { Id: upkeepId.toString() }, - ]) - - for (let i = 0; i < 256; i++) { - await ethers.provider.send('evm_mine', []) - } - - // Try to transmit a report which is older than 256 blocks so block hash cannot be matched - const tx = await registry - .connect(keeper1) - .transmit( - [emptyBytes32, emptyBytes32, emptyBytes32], - latestBlockReport, - [], - [], - emptyBytes32, - ) - - const receipt = await tx.wait() - const reorgedUpkeepReportLogs = parseReorgedUpkeepReportLogs(receipt) - // exactly 1 ReorgedUpkeepReportLogs log should be emitted - assert.equal(reorgedUpkeepReportLogs.length, 1) - }) - - it('returns early when upkeep is cancelled and cancellation delay has gone', async () => { - const latestBlockReport = await encodeLatestBlockReport([ - { Id: upkeepId.toString() }, - ]) - await registry.connect(admin).cancelUpkeep(upkeepId) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - const tx = await getTransmitTxWithReport( - registry, - keeper1, - latestBlockReport, - f + 1, - ) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('does not revert if the target cannot execute', async () => { - mock.setCanPerform(false) - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const success = upkeepPerformedLog.args.success - assert.equal(success, false) - }) - - it('reverts if not enough gas supplied', async () => { - mock.setPerformGasToBurn(executeGas) - await evmRevert( - getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1, { - gasLimit: executeGas, - }), - ) - }) - - it('executes the data passed to the registry', async () => { - mock.setCanPerform(true) - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - {}, - randomBytes, - ) - const receipt = await tx.wait() - - const upkeepPerformedWithABI = [ - 'event UpkeepPerformedWith(bytes upkeepData)', - ] - const iface = new ethers.utils.Interface(upkeepPerformedWithABI) - const parsedLogs = [] - for (let i = 0; i < receipt.logs.length; i++) { - const log = receipt.logs[i] - try { - parsedLogs.push(iface.parseLog(log)) - } catch (e) { - // ignore log - } - } - assert.equal(parsedLogs.length, 1) - assert.equal(parsedLogs[0].args.upkeepData, randomBytes) - }) - - it('uses actual execution price for payment and premium calculation', async () => { - // Actual multiplier is 2, but we set gasPrice to be 1x gasWei - const gasPrice = gasWei.mul(BigNumber.from('1')) - mock.setCanPerform(true) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - { gasPrice }, - ) - const receipt = await tx.wait() - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - BigNumber.from('1'), // Not the config multiplier, but the actual gas used - paymentPremiumPPB, - flatFeeMicroLink, - ).total.toString(), - totalPayment.toString(), - ) - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - BigNumber.from('1'), // Not the config multiplier, but the actual gas used - paymentPremiumPPB, - flatFeeMicroLink, - ).premium.toString(), - premium.toString(), - ) - }) - - it('only pays at a rate up to the gas ceiling [ @skip-coverage ]', async () => { - // Actual multiplier is 2, but we set gasPrice to be 10x - const gasPrice = gasWei.mul(BigNumber.from('10')) - mock.setCanPerform(true) - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - { gasPrice }, - ) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, // Should be same with exisitng multiplier - paymentPremiumPPB, - flatFeeMicroLink, - ).total.toString(), - totalPayment.toString(), - ) - }) - - it('correctly accounts for l1 payment', async () => { - mock.setCanPerform(true) - // Same as MockArbGasInfo.sol - const l1CostWeiArb = BigNumber.from(1000000) - - // Deploy a new registry since we change payment model - const registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - Mode.ARBITRUM, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - // Deploy a new registry since we change payment model - const registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - let tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - await linkToken.connect(owner).approve(registry.address, toWei('1000')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - - // Do the thing - tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - { gasPrice: gasWei.mul('5') }, // High gas price so that it gets capped - ) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, - paymentPremiumPPB, - flatFeeMicroLink, - l1CostWeiArb.div(gasCeilingMultiplier), // Dividing by gasCeilingMultiplier as it gets multiplied later - ).total.toString(), - totalPayment.toString(), - ) - }) - - it('can self fund', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - - await autoFunderUpkeep.setUpkeepId(upkeepId) - // Give enough funds for upkeep as well as to the upkeep contract - await linkToken - .connect(owner) - .transfer(autoFunderUpkeep.address, toWei('1000')) - const maxPayment = await registry.getMaxPaymentForGas(executeGas) - - // First set auto funding amount to 0 and verify that balance is deducted upon performUpkeep - let initialBalance = toWei('100') - await registry.connect(owner).addFunds(upkeepId, initialBalance) - await autoFunderUpkeep.setAutoFundLink(0) - await autoFunderUpkeep.setIsEligible(true) - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - - let postUpkeepBalance = (await registry.getUpkeep(upkeepId)).balance - assert.isTrue(postUpkeepBalance.lt(initialBalance)) // Balance should be deducted - assert.isTrue(postUpkeepBalance.gte(initialBalance.sub(maxPayment))) // Balance should not be deducted more than maxPayment - - // Now set auto funding amount to 100 wei and verify that the balance increases - initialBalance = postUpkeepBalance - const autoTopupAmount = toWei('100') - await autoFunderUpkeep.setAutoFundLink(autoTopupAmount) - await autoFunderUpkeep.setIsEligible(true) - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - - postUpkeepBalance = (await registry.getUpkeep(upkeepId)).balance - // Balance should increase by autoTopupAmount and decrease by max maxPayment - assert.isTrue( - postUpkeepBalance.gte( - initialBalance.add(autoTopupAmount).sub(maxPayment), - ), - ) - }) - - it('can self cancel', async () => { - const autoFunderUpkeep = await upkeepAutoFunderFactory - .connect(owner) - .deploy(linkToken.address, registry.address) - const tx = await registry - .connect(owner) - .registerUpkeep( - autoFunderUpkeep.address, - executeGas, - autoFunderUpkeep.address, - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - - await autoFunderUpkeep.setUpkeepId(upkeepId) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - - await autoFunderUpkeep.setIsEligible(true) - await autoFunderUpkeep.setShouldCancel(true) - - let registration = await registry.getUpkeep(upkeepId) - const oldExpiration = registration.maxValidBlocknumber - - // Do the thing - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - - // Verify upkeep gets cancelled - registration = await registry.getUpkeep(upkeepId) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - - it('reverts when configDigest mismatches', async () => { - const report = await encodeLatestBlockReport([ - { - Id: upkeepId.toString(), - }, - ]) - const reportContext = [emptyBytes32, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, signers.slice(0, f + 1)) - await evmRevert( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - 'ConfigDigestMismatch()', - ) - }) - - it('reverts with incorrect number of signatures', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await encodeLatestBlockReport([ - { - Id: upkeepId.toString(), - }, - ]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, signers.slice(0, f + 2)) - await evmRevert( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - 'IncorrectNumberOfSignatures()', - ) - }) - - it('reverts with invalid signature for inactive signers', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await encodeLatestBlockReport([ - { - Id: upkeepId.toString(), - }, - ]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, [ - new ethers.Wallet(ethers.Wallet.createRandom()), - new ethers.Wallet(ethers.Wallet.createRandom()), - ]) - await evmRevert( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - 'OnlyActiveSigners()', - ) - }) - - it('reverts with invalid signature for duplicated signers', async () => { - const configDigest = (await registry.getState()).state - .latestConfigDigest - const report = await encodeLatestBlockReport([ - { - Id: upkeepId.toString(), - }, - ]) - const reportContext = [configDigest, epochAndRound5_1, emptyBytes32] // wrong config digest - const sigs = signReport(reportContext, report, [signer1, signer1]) - await evmRevert( - registry - .connect(keeper1) - .transmit( - [reportContext[0], reportContext[1], reportContext[2]], - report, - sigs.rs, - sigs.ss, - sigs.vs, - ), - 'DuplicateSigners()', - ) - }) - - it('has a large enough gas overhead to cover upkeep that use all its gas [ @skip-coverage ]', async () => { - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - 10, // maximise f to maximise overhead - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - const tx = await registry.connect(owner).registerUpkeep( - mock.address, - maxPerformGas, // max allowed gas - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - - let performData = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - performData += '11' - } // max allowed performData - - mock.setCanPerform(true) - mock.setPerformGasToBurn(maxPerformGas) - - await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - 11, - { gasLimit: maxPerformGas.add(transmitGasOverhead) }, - performData, - ) // Should not revert - }) - - it('performs upkeep, deducts payment, updates lastPerformBlockNumber and emits events', async () => { - for (const i in fArray) { - const newF = fArray[i] - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - newF, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - mock.setCanPerform(true) - const checkBlock = await ethers.provider.getBlock('latest') - - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationBefore = await registry.getUpkeep(upkeepId) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - - // Do the thing - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - newF + 1, - {}, - '0x', - checkBlock.number - 1, - checkBlock.parentHash, - ) - - const receipt = await tx.wait() - - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const id = upkeepPerformedLog.args.id - const success = upkeepPerformedLog.args.success - const checkBlockNumber = upkeepPerformedLog.args.checkBlockNumber - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal(id.toString(), upkeepId.toString()) - assert.equal(success, true) - assert.equal( - checkBlockNumber.toString(), - (checkBlock.number - 1).toString(), - ) - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(totalPayment.gt(BigNumber.from('0'))) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationAfter = await registry.getUpkeep(upkeepId) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - // Keeper payment is gasPayment + premium / num keepers - const keeperPayment = totalPayment - .sub(premium) - .add(premium.div(BigNumber.from(keeperAddresses.length))) - - assert.equal( - keeperAfter.balance.sub(keeperPayment).toString(), - keeperBefore.balance.toString(), - ) - assert.equal( - registrationBefore.balance.sub(totalPayment).toString(), - registrationAfter.balance.toString(), - ) - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - - // Amount spent should be updated correctly - assert.equal( - registrationAfter.amountSpent.sub(totalPayment).toString(), - registrationBefore.amountSpent.toString(), - ) - assert.isTrue( - registrationAfter.amountSpent - .sub(registrationBefore.amountSpent) - .eq(registrationBefore.balance.sub(registrationAfter.balance)), - ) - // Last perform block number should be updated - assert.equal( - registrationAfter.lastPerformBlockNumber.toString(), - tx.blockNumber?.toString(), - ) - - // Latest epoch should be 5 - assert.equal((await registry.getState()).state.latestEpoch, 5) - } - }) - - it('calculates gas overhead appropriately within a margin for different scenarios [ @skip-coverage ]', async () => { - // Perform the upkeep once to remove non-zero storage slots and have predictable gas measurement - - let tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - - await tx.wait() - - // Different test scenarios - let longBytes = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - longBytes += '11' - } - const upkeepSuccessArray = [true, false] - const performGasArray = [5000, 100000, executeGas] - const performDataArray = ['0x', randomBytes, longBytes] - - for (const i in upkeepSuccessArray) { - for (const j in performGasArray) { - for (const k in performDataArray) { - for (const l in fArray) { - const upkeepSuccess = upkeepSuccessArray[i] - const performGas = performGasArray[j] - const performData = performDataArray[k] - const newF = fArray[l] - - mock.setCanPerform(upkeepSuccess) - mock.setPerformGasToBurn(performGas) - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - newF, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - newF + 1, - {}, - performData, - ) - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly 1 Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, 1) - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const upkeepGasUsed = upkeepPerformedLog.args.gasUsed - const chargedGasOverhead = upkeepPerformedLog.args.gasOverhead - const actualGasOverhead = receipt.gasUsed.sub(upkeepGasUsed) - - assert.isTrue(upkeepGasUsed.gt(BigNumber.from('0'))) - assert.isTrue(chargedGasOverhead.gt(BigNumber.from('0'))) - - if (i == '0' && j == '0' && k == '0') { - console.log( - 'Gas Benchmarking - sig verification ( f =', - newF, - '): calculated overhead: ', - chargedGasOverhead.toString(), - ' actual overhead: ', - actualGasOverhead.toString(), - ' margin over gasUsed: ', - chargedGasOverhead.sub(actualGasOverhead).toString(), - ) - } - - // Overhead should not get capped - const gasOverheadCap = registryGasOverhead - .add( - registryPerSignerGasOverhead.mul(BigNumber.from(newF + 1)), - ) - .add( - BigNumber.from( - registryPerPerformByteGasOverhead.toNumber() * - performData.length, - ), - ) - const gasCapMinusOverhead = - gasOverheadCap.sub(chargedGasOverhead) - assert.isTrue( - gasCapMinusOverhead.gt(BigNumber.from(0)), - 'Gas overhead got capped. Verify gas overhead variables in test match those in the registry. To not have the overheads capped increase REGISTRY_GAS_OVERHEAD by atleast ' + - gasCapMinusOverhead.toString(), - ) - // total gas charged should be greater than tx gas but within gasCalculationMargin - assert.isTrue( - chargedGasOverhead.gt(actualGasOverhead), - 'Gas overhead calculated is too low, increase account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + - actualGasOverhead.sub(chargedGasOverhead).toString(), - ) - - assert.isTrue( - chargedGasOverhead - .sub(actualGasOverhead) - .lt(BigNumber.from(gasCalculationMargin)), - ), - 'Gas overhead calculated is too high, decrease account gas variables (ACCOUNTING_FIXED_GAS_OVERHEAD/ACCOUNTING_PER_SIGNER_GAS_OVERHEAD) by atleast ' + - chargedGasOverhead - .sub(chargedGasOverhead) - .sub(BigNumber.from(gasCalculationMargin)) - .toString() - } - } - } - } - }) - }) - - describe('When upkeeps are batched', () => { - const numPassingUpkeepsArray = [1, 2, 10] - const numFailingUpkeepsArray = [0, 1, 3] - - numPassingUpkeepsArray.forEach(function (numPassingUpkeeps) { - numFailingUpkeepsArray.forEach(function (numFailingUpkeeps) { - describe( - 'passing upkeeps ' + - numPassingUpkeeps.toString() + - ', failing upkeeps ' + - numFailingUpkeeps.toString(), - () => { - let passingUpkeepIds: string[] - let failingUpkeepIds: string[] - - beforeEach(async () => { - passingUpkeepIds = [] - failingUpkeepIds = [] - for (let i = 0; i < numPassingUpkeeps; i++) { - mock = await upkeepMockFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - passingUpkeepIds.push(upkeepId.toString()) - - // Add funds to passing upkeeps - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - } - for (let i = 0; i < numFailingUpkeeps; i++) { - mock = await upkeepMockFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - failingUpkeepIds.push(upkeepId.toString()) - } - }) - - it('performs successful upkeeps and does not change failing upkeeps', async () => { - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const keeperLinkBefore = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkBefore = await linkToken.balanceOf( - registry.address, - ) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const registrationPassingBefore = await Promise.all( - passingUpkeepIds.map(async (id) => { - const reg = await registry.getUpkeep(BigNumber.from(id)) - assert.equal(reg.lastPerformBlockNumber.toString(), '0') - return reg - }), - ) - const registrationFailingBefore = await await Promise.all( - failingUpkeepIds.map(async (id) => { - const reg = await registry.getUpkeep(BigNumber.from(id)) - assert.equal(reg.lastPerformBlockNumber.toString(), '0') - return reg - }), - ) - - const tx = await getTransmitTx( - registry, - keeper1, - passingUpkeepIds.concat(failingUpkeepIds), - f + 1, - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, numPassingUpkeeps) - const insufficientFundsLogs = - parseInsufficientFundsUpkeepReportLogs(receipt) - // exactly numFailingUpkeeps Upkeep Performed should be emitted - assert.equal(insufficientFundsLogs.length, numFailingUpkeeps) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const keeperLinkAfter = await linkToken.balanceOf( - await keeper1.getAddress(), - ) - const registryLinkAfter = await linkToken.balanceOf( - registry.address, - ) - const registrationPassingAfter = await Promise.all( - passingUpkeepIds.map(async (id) => { - return await registry.getUpkeep(BigNumber.from(id)) - }), - ) - const registrationFailingAfter = await await Promise.all( - failingUpkeepIds.map(async (id) => { - return await registry.getUpkeep(BigNumber.from(id)) - }), - ) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const premium = registryPremiumAfter.sub(registryPremiumBefore) - - let netPayment = BigNumber.from('0') - for (let i = 0; i < numPassingUpkeeps; i++) { - const id = upkeepPerformedLogs[i].args.id - const gasUsed = upkeepPerformedLogs[i].args.gasUsed - const gasOverhead = upkeepPerformedLogs[i].args.gasOverhead - const totalPayment = upkeepPerformedLogs[i].args.totalPayment - - assert.equal(id.toString(), passingUpkeepIds[i]) - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - assert.isTrue(totalPayment.gt(BigNumber.from('0'))) - - // Balance should be deducted - assert.equal( - registrationPassingBefore[i].balance - .sub(totalPayment) - .toString(), - registrationPassingAfter[i].balance.toString(), - ) - - // Amount spent should be updated correctly - assert.equal( - registrationPassingAfter[i].amountSpent - .sub(totalPayment) - .toString(), - registrationPassingBefore[i].amountSpent.toString(), - ) - - // Last perform block number should be updated - assert.equal( - registrationPassingAfter[ - i - ].lastPerformBlockNumber.toString(), - tx.blockNumber?.toString(), - ) - - netPayment = netPayment.add(totalPayment) - } - - for (let i = 0; i < numFailingUpkeeps; i++) { - // InsufficientFunds log should be emitted - const id = insufficientFundsLogs[i].args.id - assert.equal(id.toString(), failingUpkeepIds[i]) - - // Balance and amount spent should be same - assert.equal( - registrationFailingBefore[i].balance.toString(), - registrationFailingAfter[i].balance.toString(), - ) - assert.equal( - registrationFailingBefore[i].amountSpent.toString(), - registrationFailingAfter[i].amountSpent.toString(), - ) - - // Last perform block number should not be updated - assert.equal( - registrationFailingAfter[ - i - ].lastPerformBlockNumber.toString(), - '0', - ) - } - - // Keeper payment is gasPayment + premium / num keepers - const keeperPayment = netPayment - .sub(premium) - .add(premium.div(BigNumber.from(keeperAddresses.length))) - - // Keeper should be paid net payment for all passed upkeeps - assert.equal( - keeperAfter.balance.sub(keeperPayment).toString(), - keeperBefore.balance.toString(), - ) - - assert.isTrue(keeperLinkAfter.eq(keeperLinkBefore)) - assert.isTrue(registryLinkBefore.eq(registryLinkAfter)) - }) - - it('splits gas overhead appropriately among performed upkeeps [ @skip-coverage ]', async () => { - // Perform the upkeeps once to remove non-zero storage slots and have predictable gas measurement - let tx = await getTransmitTx( - registry, - keeper1, - passingUpkeepIds.concat(failingUpkeepIds), - f + 1, - ) - - await tx.wait() - - // Do the actual thing - - tx = await getTransmitTx( - registry, - keeper1, - passingUpkeepIds.concat(failingUpkeepIds), - f + 1, - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, numPassingUpkeeps) - - const gasOverheadCap = registryGasOverhead.add( - registryPerSignerGasOverhead.mul(BigNumber.from(f + 1)), - ) - - const overheadCanGetCapped = - numPassingUpkeeps == 1 && numFailingUpkeeps > 0 - // Should only happen with 1 successful upkeep and some failing upkeeps. - // With 2 successful upkeeps and upto 3 failing upkeeps, overhead should be small enough to not get capped - let netGasUsedPlusOverhead = BigNumber.from('0') - - for (let i = 0; i < numPassingUpkeeps; i++) { - const gasUsed = upkeepPerformedLogs[i].args.gasUsed - const gasOverhead = upkeepPerformedLogs[i].args.gasOverhead - - assert.isTrue(gasUsed.gt(BigNumber.from('0'))) - assert.isTrue(gasOverhead.gt(BigNumber.from('0'))) - - // Overhead should not exceed capped - assert.isTrue(gasOverhead.lte(gasOverheadCap)) - - // Overhead should be same for every upkeep since they have equal performData, hence same caps - assert.isTrue( - gasOverhead.eq(upkeepPerformedLogs[0].args.gasOverhead), - ) - - netGasUsedPlusOverhead = netGasUsedPlusOverhead - .add(gasUsed) - .add(gasOverhead) - } - - const overheadsGotCapped = - upkeepPerformedLogs[0].args.gasOverhead.eq(gasOverheadCap) - // Should only get capped in certain scenarios - if (overheadsGotCapped) { - assert.isTrue( - overheadCanGetCapped, - 'Gas overhead got capped. Verify gas overhead variables in test match those in the registry. To not have the overheads capped increase REGISTRY_GAS_OVERHEAD', - ) - } - - console.log( - 'Gas Benchmarking - batching (passedUpkeeps: ', - numPassingUpkeeps, - 'failedUpkeeps:', - numFailingUpkeeps, - '): ', - 'overheadsGotCapped', - overheadsGotCapped, - 'calculated overhead', - upkeepPerformedLogs[0].args.gasOverhead.toString(), - ' margin over gasUsed', - netGasUsedPlusOverhead.sub(receipt.gasUsed).toString(), - ) - - // If overheads dont get capped then total gas charged should be greater than tx gas - // We don't check whether the net is within gasMargin as the margin changes with numFailedUpkeeps - // Which is ok, as long as individual gas overhead is capped - if (!overheadsGotCapped) { - assert.isTrue( - netGasUsedPlusOverhead.gt(receipt.gasUsed), - 'Gas overhead is too low, increase ACCOUNTING_PER_UPKEEP_GAS_OVERHEAD', - ) - } - }) - }, - ) - }) - }) - - it('has enough perform gas overhead for large batches [ @skip-coverage ]', async () => { - const numUpkeeps = 20 - const upkeepIds: string[] = [] - let totalExecuteGas = BigNumber.from('0') - for (let i = 0; i < numUpkeeps; i++) { - mock = await upkeepMockFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - upkeepIds.push(upkeepId.toString()) - - // Add funds to passing upkeeps - await registry.connect(owner).addFunds(upkeepId, toWei('10')) - - mock.setCanPerform(true) - mock.setPerformGasToBurn(executeGas) - - totalExecuteGas = totalExecuteGas.add(executeGas) - } - - // Should revert with no overhead added - await evmRevert( - getTransmitTx(registry, keeper1, upkeepIds, f + 1, { - gasLimit: totalExecuteGas, - }), - ) - // Should not revert with overhead added - await getTransmitTx(registry, keeper1, upkeepIds, f + 1, { - gasLimit: totalExecuteGas.add(transmitGasOverhead), - }) - }) - - it('splits l2 payment among performed upkeeps', async () => { - const numUpkeeps = 7 - const upkeepIds: string[] = [] - // Same as MockArbGasInfo.sol - const l1CostWeiArb = BigNumber.from(1000000) - - // Deploy a new registry since we change payment model - const registryLogic = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - Mode.ARBITRUM, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - // Deploy a new registry since we change payment model - const registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - await linkToken.connect(owner).approve(registry.address, toWei('10000')) - for (let i = 0; i < numUpkeeps; i++) { - mock = await upkeepMockFactory.deploy() - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId = await getUpkeepID(tx) - upkeepIds.push(upkeepId.toString()) - - // Add funds to passing upkeeps - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - } - - // Do the thing - const tx = await getTransmitTx( - registry, - keeper1, - upkeepIds, - f + 1, - { gasPrice: gasWei.mul('5') }, // High gas price so that it gets capped - ) - - const receipt = await tx.wait() - const upkeepPerformedLogs = parseUpkeepPerformedLogs(receipt) - // exactly numPassingUpkeeps Upkeep Performed should be emitted - assert.equal(upkeepPerformedLogs.length, numUpkeeps) - - // Verify the payment calculation in upkeepPerformed[0] - const upkeepPerformedLog = upkeepPerformedLogs[0] - - const gasUsed = upkeepPerformedLog.args.gasUsed - const gasOverhead = upkeepPerformedLog.args.gasOverhead - const totalPayment = upkeepPerformedLog.args.totalPayment - - assert.equal( - linkForGas( - gasUsed, - gasOverhead, - gasCeilingMultiplier, - paymentPremiumPPB, - flatFeeMicroLink, - l1CostWeiArb.div(gasCeilingMultiplier), // Dividing by gasCeilingMultiplier as it gets multiplied later - BigNumber.from(numUpkeeps), - ).total.toString(), - totalPayment.toString(), - ) - }) - }) - }) - - describe('#recoverFunds', () => { - const sent = toWei('7') - - beforeEach(async () => { - await linkToken.connect(admin).approve(registry.address, toWei('100')) - await linkToken - .connect(owner) - .transfer(await keeper1.getAddress(), toWei('1000')) - - // add funds to upkeep 1 and perform and withdraw some payment - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ) - - const id1 = await getUpkeepID(tx) - await registry.connect(admin).addFunds(id1, toWei('5')) - - await getTransmitTx(registry, keeper1, [id1.toString()], f + 1) - await getTransmitTx(registry, keeper2, [id1.toString()], f + 1) - await getTransmitTx(registry, keeper3, [id1.toString()], f + 1) - - await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds directly to the registry - await linkToken.connect(keeper1).transfer(registry.address, sent) - - // add funds to upkeep 2 and perform and withdraw some payment - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ) - const id2 = await getUpkeepID(tx2) - await registry.connect(admin).addFunds(id2, toWei('5')) - - await getTransmitTx(registry, keeper1, [id2.toString()], f + 1) - await getTransmitTx(registry, keeper2, [id2.toString()], f + 1) - await getTransmitTx(registry, keeper3, [id2.toString()], f + 1) - - await registry - .connect(payee2) - .withdrawPayment( - await keeper2.getAddress(), - await nonkeeper.getAddress(), - ) - - // transfer funds using onTokenTransfer - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [id2]) - await linkToken - .connect(owner) - .transferAndCall(registry.address, toWei('1'), data) - - // withdraw some funds - await registry.connect(owner).cancelUpkeep(id1) - await registry - .connect(admin) - .withdrawFunds(id1, await nonkeeper.getAddress()) - }) - - it('reverts if not called by owner', async () => { - await evmRevert( - registry.connect(keeper1).recoverFunds(), - 'Only callable by owner', - ) - }) - - it('allows any funds that have been accidentally transfered to be moved', async () => { - const balanceBefore = await linkToken.balanceOf(registry.address) - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).recoverFunds() - - const balanceAfter = await linkToken.balanceOf(registry.address) - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - assert.isTrue(balanceBefore.eq(balanceAfter.add(sent))) - assert.isTrue(ownerAfter.eq(ownerBefore.add(sent))) - }) - }) - - describe('#getMinBalanceForUpkeep / #checkUpkeep / #transmit', () => { - it('calculates the minimum balance appropriately', async () => { - await mock.setCanCheck(true) - - const oneWei = BigNumber.from(1) - const minBalance = await registry.getMinBalanceForUpkeep(upkeepId) - const tooLow = minBalance.sub(oneWei) - - await registry.connect(admin).addFunds(upkeepId, tooLow) - let checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - - await registry.connect(admin).addFunds(upkeepId, oneWei) - checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - assert.equal(checkUpkeepResult.upkeepNeeded, true) - }) - - it('uses maxPerformData size in checkUpkeep but actual performDataSize in transmit', async () => { - const tx1 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - const upkeepID1 = await getUpkeepID(tx1) - const tx2 = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - const upkeepID2 = await getUpkeepID(tx2) - await mock.setCanCheck(true) - await mock.setCanPerform(true) - - // upkeep 1 is underfunded, 2 is fully funded - const minBalance1 = ( - await registry.getMinBalanceForUpkeep(upkeepID1) - ).sub(1) - const minBalance2 = await registry.getMinBalanceForUpkeep(upkeepID2) - await registry.connect(owner).addFunds(upkeepID1, minBalance1) - await registry.connect(owner).addFunds(upkeepID2, minBalance2) - - // upkeep 1 check should return false, 2 should return true - let checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID1) - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - - checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepID2) - assert.equal(checkUpkeepResult.upkeepNeeded, true) - - // upkeep 1 perform should return with insufficient balance using max performData size - let maxPerformData = '0x' - for (let i = 0; i < maxPerformDataSize.toNumber(); i++) { - maxPerformData += '11' - } - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepID1.toString()], - f + 1, - { gasPrice: gasWei.mul(gasCeilingMultiplier) }, - maxPerformData, - ) - - const receipt = await tx.wait() - const insufficientFundsUpkeepReportLogs = - parseInsufficientFundsUpkeepReportLogs(receipt) - // exactly 1 InsufficientFundsUpkeepReportLogs log should be emitted - assert.equal(insufficientFundsUpkeepReportLogs.length, 1) - - // upkeep 1 perform should succeed with empty performData - await getTransmitTx( - registry, - keeper1, - [upkeepID1.toString()], - f + 1, - { gasPrice: gasWei.mul(gasCeilingMultiplier) }, - '0x', - ), - // upkeep 2 perform should succeed with max performData size - await getTransmitTx( - registry, - keeper1, - [upkeepID2.toString()], - f + 1, - { gasPrice: gasWei.mul(gasCeilingMultiplier) }, - maxPerformData, - ) - }) - }) - - describe('#withdrawFunds', () => { - let upkeepId2: BigNumber - - beforeEach(async () => { - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId2 = await getUpkeepID(tx) - - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - await registry.connect(admin).addFunds(upkeepId2, toWei('100')) - - // Do a perform so that upkeep is charged some amount - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - await getTransmitTx(registry, keeper1, [upkeepId2.toString()], f + 1) - }) - - it('reverts if called on a non existing ID', async () => { - await evmRevert( - registry - .connect(admin) - .withdrawFunds(upkeepId.add(1), await payee1.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry - .connect(owner) - .withdrawFunds(upkeepId, await payee1.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if called on an uncanceled upkeep', async () => { - await evmRevert( - registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()), - 'UpkeepNotCanceled()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry.connect(admin).withdrawFunds(upkeepId, zeroAddress), - 'InvalidRecipient()', - ) - }) - - describe('after the registration is cancelled', () => { - beforeEach(async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - await registry.connect(owner).cancelUpkeep(upkeepId2) - }) - - it('can be called successively on two upkeeps', async () => { - await registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()) - await registry - .connect(admin) - .withdrawFunds(upkeepId2, await payee1.getAddress()) - }) - - it('moves the funds out and updates the balance and emits an event', async () => { - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const registryBefore = await linkToken.balanceOf(registry.address) - - let registration = await registry.getUpkeep(upkeepId) - const previousBalance = registration.balance - - const tx = await registry - .connect(admin) - .withdrawFunds(upkeepId, await payee1.getAddress()) - await expect(tx) - .to.emit(registry, 'FundsWithdrawn') - .withArgs(upkeepId, previousBalance, await payee1.getAddress()) - - const payee1After = await linkToken.balanceOf(await payee1.getAddress()) - const registryAfter = await linkToken.balanceOf(registry.address) - - assert.isTrue(payee1Before.add(previousBalance).eq(payee1After)) - assert.isTrue(registryBefore.sub(previousBalance).eq(registryAfter)) - - registration = await registry.getUpkeep(upkeepId) - assert.equal(0, registration.balance.toNumber()) - }) - }) - }) - - describe('#simulatePerformUpkeep', () => { - it('reverts if called by non zero address', async () => { - await evmRevert( - registry - .connect(await owner.getAddress()) - .callStatic.simulatePerformUpkeep(upkeepId, '0x'), - 'OnlySimulatedBackend()', - ) - }) - - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevert( - registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x'), - 'RegistryPaused()', - ) - }) - - it('returns false and gasUsed when perform fails', async () => { - await mock.setCanPerform(false) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, false) - assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns true and gasUsed when perform succeeds', async () => { - await mock.setCanPerform(true) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, true) - assert.isTrue(simulatePerformResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns correct amount of gasUsed when perform succeeds', async () => { - await mock.setCanPerform(true) - await mock.setPerformGasToBurn(executeGas) - - const simulatePerformResult = await registry - .connect(zeroAddress) - .callStatic.simulatePerformUpkeep(upkeepId, '0x') - - assert.equal(simulatePerformResult.success, true) - // Full execute gas should be used, with some performGasBuffer(1000) - assert.isTrue( - simulatePerformResult.gasUsed.gt( - executeGas.sub(BigNumber.from('1000')), - ), - ) - }) - }) - - describe('#checkUpkeep', () => { - it('reverts if called by non zero address', async () => { - await evmRevert( - registry - .connect(await owner.getAddress()) - .callStatic.checkUpkeep(upkeepId), - 'OnlySimulatedBackend()', - ) - }) - - it('returns false and error code if the upkeep is cancelled by admin', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_CANCELLED, - ) - assert.equal(checkUpkeepResult.gasUsed.toString(), '0') - }) - - it('returns false and error code if the upkeep is cancelled by owner', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_CANCELLED, - ) - assert.equal(checkUpkeepResult.gasUsed.toString(), '0') - }) - - it('returns false and error code if the upkeep is paused', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_PAUSED, - ) - assert.equal(checkUpkeepResult.gasUsed.toString(), '0') - }) - - it('returns false and error code if user is out of funds', async () => { - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.INSUFFICIENT_BALANCE, - ) - assert.equal(checkUpkeepResult.gasUsed.toString(), '0') - }) - - context('when the registration is funded', () => { - beforeEach(async () => { - await linkToken.connect(admin).approve(registry.address, toWei('100')) - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - }) - - it('returns false, error code, and revert data if the target check reverts', async () => { - await mock.setShouldRevertCheck(true) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - assert.equal(checkUpkeepResult.upkeepNeeded, false) - - const wrappedPerfromData = ethers.utils.defaultAbiCoder.decode( - [ - 'tuple(uint32 checkBlockNum, bytes32 checkBlockHash, bytes performData)', - ], - checkUpkeepResult.performData, - ) - const revertReasonBytes = `0x${wrappedPerfromData[0][2].slice(10)}` // remove sighash - assert.equal( - ethers.utils.defaultAbiCoder.decode(['string'], revertReasonBytes)[0], - 'shouldRevertCheck should be false', - ) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.TARGET_CHECK_REVERTED, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns false and error code if the upkeep is not needed', async () => { - await mock.setCanCheck(false) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.UPKEEP_NOT_NEEDED, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns false and error code if the performData exceeds limit', async () => { - let longBytes = '0x' - for (let i = 0; i < 5000; i++) { - longBytes += '1' - } - await mock.setCanCheck(true) - await mock.setPerformData(longBytes) - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId) - - assert.equal(checkUpkeepResult.upkeepNeeded, false) - assert.equal(checkUpkeepResult.performData, '0x') - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.PERFORM_DATA_EXCEEDS_LIMIT, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - }) - - it('returns true with wrapped perform data and gas used if the target can execute', async () => { - await mock.setCanCheck(true) - await mock.setPerformData(randomBytes) - - const latestBlock = await ethers.provider.getBlock('latest') - - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId, { - blockTag: latestBlock.number, - }) - - const wrappedPerfromData = ethers.utils.defaultAbiCoder.decode( - [ - 'tuple(uint32 checkBlockNum, bytes32 checkBlockHash, bytes performData)', - ], - checkUpkeepResult.performData, - ) - - assert.equal(checkUpkeepResult.upkeepNeeded, true) - assert.equal( - wrappedPerfromData[0].checkBlockNum, - latestBlock.number - 1, - ) - assert.equal( - wrappedPerfromData[0].checkBlockHash, - latestBlock.parentHash, - ) - assert.equal(wrappedPerfromData[0].performData, randomBytes) - assert.equal( - checkUpkeepResult.upkeepFailureReason, - UpkeepFailureReason.NONE, - ) - assert.isTrue(checkUpkeepResult.gasUsed.gt(BigNumber.from('0'))) // Some gas should be used - assert.isTrue(checkUpkeepResult.fastGasWei.eq(gasWei)) - assert.isTrue(checkUpkeepResult.linkNative.eq(linkEth)) - }) - - it('has a large enough gas overhead to cover upkeeps that use all their gas [ @skip-coverage ]', async () => { - await mock.setCanCheck(true) - await mock.setCheckGasToBurn(checkGasLimit) - const gas = checkGasLimit.add(checkGasOverhead) - const checkUpkeepResult = await registry - .connect(zeroAddress) - .callStatic.checkUpkeep(upkeepId, { - gasLimit: gas, - }) - - assert.equal(checkUpkeepResult.upkeepNeeded, true) - }) - }) - }) - - describe('#addFunds', () => { - const amount = toWei('1') - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).addFunds(upkeepId.add(1), amount), - 'UpkeepCancelled()', - ) - }) - - it('adds to the balance of the registration', async () => { - await registry.connect(admin).addFunds(upkeepId, amount) - const registration = await registry.getUpkeep(upkeepId) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('lets anyone add funds to an upkeep not just admin', async () => { - await linkToken.connect(owner).transfer(await payee1.getAddress(), amount) - await linkToken.connect(payee1).approve(registry.address, amount) - - await registry.connect(payee1).addFunds(upkeepId, amount) - const registration = await registry.getUpkeep(upkeepId) - assert.isTrue(amount.eq(registration.balance)) - }) - - it('emits a log', async () => { - const tx = await registry.connect(admin).addFunds(upkeepId, amount) - await expect(tx) - .to.emit(registry, 'FundsAdded') - .withArgs(upkeepId, await admin.getAddress(), amount) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevert( - registry.connect(keeper1).addFunds(upkeepId, amount), - 'UpkeepCancelled()', - ) - }) - }) - - describe('#getActiveUpkeepIDs', () => { - let upkeepId2: BigNumber - - beforeEach(async () => { - // Register another upkeep so that we have 2 - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - randomBytes, - emptyBytes, - ) - upkeepId2 = await getUpkeepID(tx) - }) - - it('reverts if startIndex is out of bounds ', async () => { - await evmRevert(registry.getActiveUpkeepIDs(4, 0), 'IndexOutOfRange()') - }) - - it('reverts if startIndex + maxCount is out of bounds', async () => { - await evmRevert(registry.getActiveUpkeepIDs(0, 4)) - }) - - it('returns upkeep IDs bounded by maxCount', async () => { - let upkeepIds = await registry.getActiveUpkeepIDs(0, 1) - assert( - upkeepIds.length == 1, - 'Only maxCount number of upkeeps should be returned', - ) - assert( - upkeepIds[0].toString() == upkeepId.toString(), - 'Correct upkeep ID should be returned', - ) - - upkeepIds = await registry.getActiveUpkeepIDs(1, 1) - assert( - upkeepIds.length == 1, - 'Only maxCount number of upkeeps should be returned', - ) - assert( - upkeepIds[0].toString() == upkeepId2.toString(), - 'Correct upkeep ID should be returned', - ) - }) - - it('returns all upkeep IDs if maxCount is 0', async () => { - const upkeepIds = await registry.getActiveUpkeepIDs(0, 0) - assert(upkeepIds.length == 2, 'All upkeeps should be returned') - assert( - upkeepIds[0].toString() == upkeepId.toString(), - 'Correct upkeep ID should be returned', - ) - assert( - upkeepIds[1].toString() == upkeepId2.toString(), - 'Correct upkeep ID should be returned', - ) - }) - }) - - describe('#getMaxPaymentForGas', () => { - const multipliers = [BigNumber.from(1), BigNumber.from(3)] - const gasAmounts = [100000, 10000000] - const premiums = [0, 250000000] - const flatFees = [0, 1000000] - // Same as MockArbGasInfo.sol - const l1CostWeiArb = BigNumber.from(1000000) - // Same as MockOVMGasPriceOracle.sol - const l1CostWeiOpt = BigNumber.from(2000000) - - it('calculates the max fee appropriately', async () => { - await verifyMaxPayment( - Mode.DEFAULT, - multipliers, - gasAmounts, - premiums, - flatFees, - ) - }) - - it('calculates the max fee appropriately for Arbitrum', async () => { - await verifyMaxPayment( - Mode.ARBITRUM, - multipliers, - gasAmounts, - premiums, - flatFees, - l1CostWeiArb, - ) - }) - - it('calculates the max fee appropriately for Optimism', async () => { - await verifyMaxPayment( - Mode.OPTIMISM, - multipliers, - gasAmounts, - premiums, - flatFees, - l1CostWeiOpt, - ) - }) - - it('uses the fallback gas price if the feed has issues', async () => { - const expectedFallbackMaxPayment = linkForGas( - executeGas, - registryGasOverhead - .add(registryPerSignerGasOverhead.mul(f + 1)) - .add(maxPerformDataSize.mul(registryPerPerformByteGasOverhead)), - gasCeilingMultiplier.mul('2'), // fallbackGasPrice is 2x gas price - paymentPremiumPPB, - flatFeeMicroLink, - ).total - - // Stale feed - let roundId = 99 - const answer = 100 - let updatedAt = 946684800 // New Years 2000 🥳 - let startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - - // Negative feed price - roundId = 100 - updatedAt = Math.floor(Date.now() / 1000) - startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - - // Zero feed price - roundId = 101 - updatedAt = Math.floor(Date.now() / 1000) - startedAt = 946684799 - await gasPriceFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - }) - - it('uses the fallback link price if the feed has issues', async () => { - const expectedFallbackMaxPayment = linkForGas( - executeGas, - registryGasOverhead - .add(registryPerSignerGasOverhead.mul(f + 1)) - .add(maxPerformDataSize.mul(registryPerPerformByteGasOverhead)), - gasCeilingMultiplier.mul('2'), // fallbackLinkPrice is 1/2 link price, so multiply by 2 - paymentPremiumPPB, - flatFeeMicroLink, - ).total - - // Stale feed - let roundId = 99 - const answer = 100 - let updatedAt = 946684800 // New Years 2000 🥳 - let startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, answer, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - - // Negative feed price - roundId = 100 - updatedAt = Math.floor(Date.now() / 1000) - startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, -100, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - - // Zero feed price - roundId = 101 - updatedAt = Math.floor(Date.now() / 1000) - startedAt = 946684799 - await linkEthFeed - .connect(owner) - .updateRoundData(roundId, 0, updatedAt, startedAt) - - assert.equal( - expectedFallbackMaxPayment.toString(), - (await registry.getMaxPaymentForGas(executeGas)).toString(), - ) - }) - }) - - describe('#typeAndVersion', () => { - it('uses the correct type and version', async () => { - const typeAndVersion = await registry.typeAndVersion() - assert.equal(typeAndVersion, 'KeeperRegistry 2.0.2') - }) - }) - - describe('#onTokenTransfer', () => { - const amount = toWei('1') - - it('reverts if not called by the LINK token', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) - - await evmRevert( - registry - .connect(keeper1) - .onTokenTransfer(await keeper1.getAddress(), amount, data), - 'OnlyCallableByLINKToken()', - ) - }) - - it('reverts if not called with more or less than 32 bytes', async () => { - const longData = ethers.utils.defaultAbiCoder.encode( - ['uint256', 'uint256'], - ['33', '34'], - ) - const shortData = '0x12345678' - - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, longData), - ) - await evmRevert( - linkToken - .connect(owner) - .transferAndCall(registry.address, amount, shortData), - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevert( - registry.connect(keeper1).addFunds(upkeepId, amount), - 'UpkeepCancelled()', - ) - }) - - it('updates the funds of the job id passed', async () => { - const data = ethers.utils.defaultAbiCoder.encode(['uint256'], [upkeepId]) - - const before = (await registry.getUpkeep(upkeepId)).balance - await linkToken - .connect(owner) - .transferAndCall(registry.address, amount, data) - const after = (await registry.getUpkeep(upkeepId)).balance - - assert.isTrue(before.add(amount).eq(after)) - }) - }) - - describe('#setConfig - onchain', () => { - const payment = BigNumber.from(1) - const flatFee = BigNumber.from(2) - const staleness = BigNumber.from(4) - const ceiling = BigNumber.from(5) - const maxGas = BigNumber.from(6) - const fbGasEth = BigNumber.from(7) - const fbLinkEth = BigNumber.from(8) - const newMinUpkeepSpend = BigNumber.from(9) - const newMaxCheckDataSize = BigNumber.from(10000) - const newMaxPerformDataSize = BigNumber.from(10000) - const newMaxPerformGas = BigNumber.from(10000000) - - it('reverts when called by anyone but the proposed owner', async () => { - await evmRevert( - registry.connect(payee1).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: newMaxPerformDataSize, - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ), - 'Only callable by owner', - ) - }) - - it('updates the onchainConfig and configDigest', async () => { - const old = await registry.getState() - const oldConfig = old.config - const oldState = old.state - assert.isTrue(paymentPremiumPPB.eq(oldConfig.paymentPremiumPPB)) - assert.isTrue(flatFeeMicroLink.eq(oldConfig.flatFeeMicroLink)) - assert.isTrue(stalenessSeconds.eq(oldConfig.stalenessSeconds)) - assert.isTrue(gasCeilingMultiplier.eq(oldConfig.gasCeilingMultiplier)) - - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: newMaxPerformDataSize, - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - - const updated = await registry.getState() - const updatedConfig = updated.config - const updatedState = updated.state - assert.equal(updatedConfig.paymentPremiumPPB, payment.toNumber()) - assert.equal(updatedConfig.flatFeeMicroLink, flatFee.toNumber()) - assert.equal(updatedConfig.stalenessSeconds, staleness.toNumber()) - assert.equal(updatedConfig.gasCeilingMultiplier, ceiling.toNumber()) - assert.equal( - updatedConfig.minUpkeepSpend.toString(), - newMinUpkeepSpend.toString(), - ) - assert.equal( - updatedConfig.maxCheckDataSize, - newMaxCheckDataSize.toNumber(), - ) - assert.equal( - updatedConfig.maxPerformDataSize, - newMaxPerformDataSize.toNumber(), - ) - assert.equal(updatedConfig.maxPerformGas, newMaxPerformGas.toNumber()) - assert.equal(updatedConfig.checkGasLimit, maxGas.toNumber()) - assert.equal( - updatedConfig.fallbackGasPrice.toNumber(), - fbGasEth.toNumber(), - ) - assert.equal( - updatedConfig.fallbackLinkPrice.toNumber(), - fbLinkEth.toNumber(), - ) - assert.equal(updatedState.latestEpoch, 0) - - assert(oldState.configCount + 1 == updatedState.configCount) - assert( - oldState.latestConfigBlockNumber != - updatedState.latestConfigBlockNumber, - ) - assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: newMaxPerformDataSize, - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - await expect(tx).to.emit(registry, 'ConfigSet') - }) - - it('reverts upon decreasing max limits', async () => { - await evmRevert( - registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: BigNumber.from(1), - maxPerformDataSize: newMaxPerformDataSize, - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ), - 'MaxCheckDataSizeCanOnlyIncrease()', - ) - await evmRevert( - registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: BigNumber.from(1), - maxPerformGas: newMaxPerformGas, - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ), - 'MaxPerformDataSizeCanOnlyIncrease()', - ) - await evmRevert( - registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB: payment, - flatFeeMicroLink: flatFee, - checkGasLimit: maxGas, - stalenessSeconds: staleness, - gasCeilingMultiplier: ceiling, - minUpkeepSpend: newMinUpkeepSpend, - maxCheckDataSize: newMaxCheckDataSize, - maxPerformDataSize: newMaxPerformDataSize, - maxPerformGas: BigNumber.from(1), - fallbackGasPrice: fbGasEth, - fallbackLinkPrice: fbLinkEth, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ), - 'GasLimitCanOnlyIncrease()', - ) - }) - }) - - describe('#setConfig - offchain', () => { - let newKeepers: string[] - - beforeEach(async () => { - newKeepers = [ - await personas.Eddy.getAddress(), - await personas.Nick.getAddress(), - await personas.Neil.getAddress(), - await personas.Carol.getAddress(), - ] - }) - - it('reverts when called by anyone but the owner', async () => { - await evmRevert( - registry - .connect(payee1) - .setConfig( - newKeepers, - newKeepers, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'Only callable by owner', - ) - }) - - it('reverts if too many keeperAddresses set', async () => { - for (let i = 0; i < 40; i++) { - newKeepers.push(randomAddress()) - } - await evmRevert( - registry - .connect(owner) - .setConfig( - newKeepers, - newKeepers, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'TooManyOracles()', - ) - }) - - it('reverts if f=0', async () => { - await evmRevert( - registry - .connect(owner) - .setConfig( - newKeepers, - newKeepers, - 0, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'IncorrectNumberOfFaultyOracles()', - ) - }) - - it('reverts if signers != transmitters length', async () => { - const signers = [randomAddress()] - await evmRevert( - registry - .connect(owner) - .setConfig( - signers, - newKeepers, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'IncorrectNumberOfSigners()', - ) - }) - - it('reverts if signers <= 3f', async () => { - newKeepers.pop() - await evmRevert( - registry - .connect(owner) - .setConfig( - newKeepers, - newKeepers, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'IncorrectNumberOfSigners()', - ) - }) - - it('reverts on repeated signers', async () => { - const newSigners = [ - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - ] - await evmRevert( - registry - .connect(owner) - .setConfig( - newSigners, - newKeepers, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'RepeatedSigner()', - ) - }) - - it('reverts on repeated transmitters', async () => { - const newTransmitters = [ - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - await personas.Eddy.getAddress(), - ] - await evmRevert( - registry - .connect(owner) - .setConfig( - newKeepers, - newTransmitters, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ), - 'RepeatedTransmitter()', - ) - }) - - it('stores new config and emits event', async () => { - // Perform an upkeep so that totalPremium is updated - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - let tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - await tx.wait() - - const newOffChainVersion = BigNumber.from('2') - const newOffChainConfig = '0x1122' - - const old = await registry.getState() - const oldState = old.state - assert(oldState.totalPremium.gt(BigNumber.from('0'))) - - const newSigners = newKeepers - tx = await registry - .connect(owner) - .setConfig( - newSigners, - newKeepers, - f, - encodeConfig(config), - newOffChainVersion, - newOffChainConfig, - ) - - const updated = await registry.getState() - const updatedState = updated.state - assert(oldState.totalPremium.eq(updatedState.totalPremium)) - - // Old signer addresses which are not in new signers should be non active - for (let i = 0; i < signerAddresses.length; i++) { - const signer = signerAddresses[i] - if (!newSigners.includes(signer)) { - assert((await registry.getSignerInfo(signer)).active == false) - assert((await registry.getSignerInfo(signer)).index == 0) - } - } - // New signer addresses should be active - for (let i = 0; i < newSigners.length; i++) { - const signer = newSigners[i] - assert((await registry.getSignerInfo(signer)).active == true) - assert((await registry.getSignerInfo(signer)).index == i) - } - // Old transmitter addresses which are not in new transmitter should be non active, update lastCollected but retain other info - for (let i = 0; i < keeperAddresses.length; i++) { - const transmitter = keeperAddresses[i] - if (!newKeepers.includes(transmitter)) { - assert( - (await registry.getTransmitterInfo(transmitter)).active == false, - ) - assert((await registry.getTransmitterInfo(transmitter)).index == i) - assert( - ( - await registry.getTransmitterInfo(transmitter) - ).lastCollected.toString() == oldState.totalPremium.toString(), - ) - } - } - // New transmitter addresses should be active - for (let i = 0; i < newKeepers.length; i++) { - const transmitter = newKeepers[i] - assert((await registry.getTransmitterInfo(transmitter)).active == true) - assert((await registry.getTransmitterInfo(transmitter)).index == i) - assert( - ( - await registry.getTransmitterInfo(transmitter) - ).lastCollected.toString() == oldState.totalPremium.toString(), - ) - } - - // config digest should be updated - assert(oldState.configCount + 1 == updatedState.configCount) - assert( - oldState.latestConfigBlockNumber != - updatedState.latestConfigBlockNumber, - ) - assert(oldState.latestConfigDigest != updatedState.latestConfigDigest) - - //New config should be updated - assert.deepEqual(updated.signers, newKeepers) - assert.deepEqual(updated.transmitters, newKeepers) - - // Event should have been emitted - await expect(tx).to.emit(registry, 'ConfigSet') - }) - }) - - describe('#setPeerRegistryMigrationPermission() / #getPeerRegistryMigrationPermission()', () => { - const peer = randomAddress() - it('allows the owner to set the peer registries', async () => { - let permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - await registry.setPeerRegistryMigrationPermission(peer, 1) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(1) - await registry.setPeerRegistryMigrationPermission(peer, 2) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(2) - await registry.setPeerRegistryMigrationPermission(peer, 0) - permission = await registry.getPeerRegistryMigrationPermission(peer) - expect(permission).to.equal(0) - }) - it('reverts if passed an unsupported permission', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 10), - ).to.be.reverted - }) - it('reverts if not called by the owner', async () => { - await expect( - registry.connect(admin).setPeerRegistryMigrationPermission(peer, 1), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('#registerUpkeep', () => { - it('reverts when registry is paused', async () => { - await registry.connect(owner).pause() - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'RegistryPaused()', - ) - }) - - it('reverts if the target is not a contract', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - zeroAddress, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'NotAContract()', - ) - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry - .connect(keeper1) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'OnlyCallableByOwnerOrRegistrar()', - ) - }) - - it('reverts if execute gas is too low', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 2299, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('reverts if execute gas is too high', async () => { - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - 5000001, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'GasLimitOutsideRange()', - ) - }) - - it('reverts if checkData is too long', async () => { - let longBytes = '0x' - for (let i = 0; i < 10000; i++) { - longBytes += '1' - } - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - longBytes, - emptyBytes, - ), - 'CheckDataExceedsLimit()', - ) - }) - - it('creates a record of the registration', async () => { - const executeGases = [100000, 500000] - const checkDatas = [emptyBytes, '0x12'] - const offchainConfig = '0x1234567890' - - for (let jdx = 0; jdx < executeGases.length; jdx++) { - const executeGas = executeGases[jdx] - for (let kdx = 0; kdx < checkDatas.length; kdx++) { - const checkData = checkDatas[kdx] - const tx = await registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - checkData, - offchainConfig, - ) - - //confirm the upkeep details - upkeepId = await getUpkeepID(tx) - await expect(tx) - .to.emit(registry, 'UpkeepRegistered') - .withArgs(upkeepId, executeGas, await admin.getAddress()) - const registration = await registry.getUpkeep(upkeepId) - - assert.equal(mock.address, registration.target) - assert.equal( - executeGas.toString(), - registration.executeGas.toString(), - ) - assert.equal(await admin.getAddress(), registration.admin) - assert.equal(0, registration.balance.toNumber()) - assert.equal(0, registration.amountSpent.toNumber()) - assert.equal(0, registration.lastPerformBlockNumber) - assert.equal(checkData, registration.checkData) - assert.equal(registration.paused, false) - assert.equal(registration.offchainConfig, offchainConfig) - assert(registration.maxValidBlocknumber.eq('0xffffffff')) - } - } - }) - }) - - describe('#pauseUpkeep', () => { - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).pauseUpkeep(upkeepId.add(1)), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevert( - registry.connect(admin).pauseUpkeep(upkeepId), - 'UpkeepCancelled()', - ) - }) - - it('reverts if the upkeep is already paused', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - await evmRevert( - registry.connect(admin).pauseUpkeep(upkeepId), - 'OnlyUnpausedUpkeep()', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await evmRevert( - registry.connect(keeper1).pauseUpkeep(upkeepId), - 'OnlyCallableByAdmin()', - ) - }) - - it('pauses the upkeep and emits an event', async () => { - const tx = await registry.connect(admin).pauseUpkeep(upkeepId) - await expect(tx).to.emit(registry, 'UpkeepPaused').withArgs(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(registration.paused, true) - }) - }) - - describe('#unpauseUpkeep', () => { - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).unpauseUpkeep(upkeepId.add(1)), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is already canceled', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - await evmRevert( - registry.connect(admin).unpauseUpkeep(upkeepId), - 'UpkeepCancelled()', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse((await registry.getState()).state.paused) - - await registry.connect(owner).pause() - - assert.isTrue((await registry.getState()).state.paused) - }) - - it('reverts if the upkeep is not paused', async () => { - await evmRevert( - registry.connect(admin).unpauseUpkeep(upkeepId), - 'OnlyPausedUpkeep()', - ) - }) - - it('reverts if the caller is not the upkeep admin', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - - assert.equal(registration.paused, true) - - await evmRevert( - registry.connect(keeper1).unpauseUpkeep(upkeepId), - 'OnlyCallableByAdmin()', - ) - }) - - it('unpauses the upkeep and emits an event', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - - const tx = await registry.connect(admin).unpauseUpkeep(upkeepId) - - await expect(tx).to.emit(registry, 'UpkeepUnpaused').withArgs(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(registration.paused, false) - - const upkeepIds = await registry.getActiveUpkeepIDs(0, 0) - assert.equal(upkeepIds.length, 1) - }) - }) - - describe('#updateCheckData', () => { - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(keeper1).updateCheckData(upkeepId.add(1), randomBytes), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the caller is not upkeep admin', async () => { - await evmRevert( - registry.connect(keeper1).updateCheckData(upkeepId, randomBytes), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevert( - registry.connect(admin).updateCheckData(upkeepId, randomBytes), - 'UpkeepCancelled()', - ) - }) - - it('is allowed to update on paused upkeep', async () => { - await registry.connect(admin).pauseUpkeep(upkeepId) - await registry.connect(admin).updateCheckData(upkeepId, randomBytes) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(randomBytes, registration.checkData) - }) - - it('reverts if newCheckData exceeds limit', async () => { - let longBytes = '0x' - for (let i = 0; i < 10000; i++) { - longBytes += '1' - } - - await evmRevert( - registry.connect(admin).updateCheckData(upkeepId, longBytes), - 'CheckDataExceedsLimit()', - ) - }) - - it('updates the upkeep check data and emits an event', async () => { - const tx = await registry - .connect(admin) - .updateCheckData(upkeepId, randomBytes) - await expect(tx) - .to.emit(registry, 'UpkeepCheckDataUpdated') - .withArgs(upkeepId, randomBytes) - - const registration = await registry.getUpkeep(upkeepId) - assert.equal(randomBytes, registration.checkData) - }) - }) - - describe('#setUpkeepGasLimit', () => { - const newGasLimit = BigNumber.from('300000') - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry.connect(admin).setUpkeepGasLimit(upkeepId.add(1), newGasLimit), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevert( - registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit), - 'UpkeepCancelled()', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry.connect(owner).setUpkeepGasLimit(upkeepId, newGasLimit), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if new gas limit is out of bounds', async () => { - await evmRevert( - registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, BigNumber.from('100')), - 'GasLimitOutsideRange()', - ) - await evmRevert( - registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, BigNumber.from('6000000')), - 'GasLimitOutsideRange()', - ) - }) - - it('updates the gas limit successfully', async () => { - const initialGasLimit = (await registry.getUpkeep(upkeepId)).executeGas - assert.equal(initialGasLimit, executeGas.toNumber()) - await registry.connect(admin).setUpkeepGasLimit(upkeepId, newGasLimit) - const updatedGasLimit = (await registry.getUpkeep(upkeepId)).executeGas - assert.equal(updatedGasLimit, newGasLimit.toNumber()) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepGasLimit(upkeepId, newGasLimit) - await expect(tx) - .to.emit(registry, 'UpkeepGasLimitSet') - .withArgs(upkeepId, newGasLimit) - }) - }) - - describe('#setUpkeepOffchainConfig', () => { - const newConfig = '0xc0ffeec0ffee' - - it('reverts if the registration does not exist', async () => { - await evmRevert( - registry - .connect(admin) - .setUpkeepOffchainConfig(upkeepId.add(1), newConfig), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts if the upkeep is canceled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - await evmRevert( - registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig), - 'UpkeepCancelled()', - ) - }) - - it('reverts if called by anyone but the admin', async () => { - await evmRevert( - registry.connect(owner).setUpkeepOffchainConfig(upkeepId, newConfig), - 'OnlyCallableByAdmin()', - ) - }) - - it('updates the config successfully', async () => { - const initialConfig = (await registry.getUpkeep(upkeepId)).offchainConfig - assert.equal(initialConfig, '0x') - await registry.connect(admin).setUpkeepOffchainConfig(upkeepId, newConfig) - const updatedConfig = (await registry.getUpkeep(upkeepId)).offchainConfig - assert.equal(newConfig, updatedConfig) - }) - - it('emits a log', async () => { - const tx = await registry - .connect(admin) - .setUpkeepOffchainConfig(upkeepId, newConfig) - await expect(tx) - .to.emit(registry, 'UpkeepOffchainConfigSet') - .withArgs(upkeepId, newConfig) - }) - }) - - describe('#transferUpkeepAdmin', () => { - it('reverts when called by anyone but the current upkeep admin', async () => { - await evmRevert( - registry - .connect(payee1) - .transferUpkeepAdmin(upkeepId, await payee2.getAddress()), - 'OnlyCallableByAdmin()', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await admin.getAddress()), - 'ValueNotChanged()', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await keeper1.getAddress()), - 'UpkeepCancelled()', - ) - }) - - it('reverts when transferring to zero address', async () => { - await evmRevert( - registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, ethers.constants.AddressZero), - 'InvalidRecipient()', - ) - }) - - it('does not change the upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - const upkeep = await registry.getUpkeep(upkeepId) - assert.equal(await admin.getAddress(), upkeep.admin) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferRequested') - .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) - }) - - it('does not emit an event when called with the same proposed upkeep admin', async () => { - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - const tx = await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptUpkeepAdmin', () => { - beforeEach(async () => { - // Start admin transfer to payee1 - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - }) - - it('reverts when not called by the proposed upkeep admin', async () => { - await evmRevert( - registry.connect(payee2).acceptUpkeepAdmin(upkeepId), - 'OnlyCallableByProposedAdmin()', - ) - }) - - it('reverts when the upkeep is cancelled', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevert( - registry.connect(payee1).acceptUpkeepAdmin(upkeepId), - 'UpkeepCancelled()', - ) - }) - - it('does change the admin', async () => { - await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) - - const upkeep = await registry.getUpkeep(upkeepId) - assert.equal(await payee1.getAddress(), upkeep.admin) - }) - - it('emits an event announcing the new upkeep admin', async () => { - const tx = await registry.connect(payee1).acceptUpkeepAdmin(upkeepId) - await expect(tx) - .to.emit(registry, 'UpkeepAdminTransferred') - .withArgs(upkeepId, await admin.getAddress(), await payee1.getAddress()) - }) - }) - - describe('#withdrawOwnerFunds', () => { - it('can only be called by owner', async () => { - await evmRevert( - registry.connect(keeper1).withdrawOwnerFunds(), - 'Only callable by owner', - ) - }) - - it('withdraws the collected fees to owner', async () => { - await registry.connect(admin).addFunds(upkeepId, toWei('100')) - // Very high min spend, whole balance as cancellation fees - const minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - const upkeepBalance = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = await linkToken.balanceOf(await owner.getAddress()) - - await registry.connect(owner).cancelUpkeep(upkeepId) - - // Transfered to owner balance on registry - let ownerRegistryBalance = (await registry.getState()).state - .ownerLinkBalance - assert.isTrue(ownerRegistryBalance.eq(upkeepBalance)) - - // Now withdraw - await registry.connect(owner).withdrawOwnerFunds() - - ownerRegistryBalance = (await registry.getState()).state.ownerLinkBalance - const ownerAfter = await linkToken.balanceOf(await owner.getAddress()) - - // Owner registry balance should be changed to 0 - assert.isTrue(ownerRegistryBalance.eq(BigNumber.from('0'))) - - // Owner should be credited with the balance - assert.isTrue(ownerBefore.add(upkeepBalance).eq(ownerAfter)) - }) - }) - - describe('#transferPayeeship', () => { - it('reverts when called by anyone but the current payee', async () => { - await evmRevert( - registry - .connect(payee2) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts when transferring to self', async () => { - await evmRevert( - registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee1.getAddress(), - ), - 'ValueNotChanged()', - ) - }) - - it('does not change the payee', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const info = await registry.getTransmitterInfo(await keeper1.getAddress()) - assert.equal(await payee1.getAddress(), info.payee) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferRequested') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does not emit an event when called with the same proposal', async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - - const tx = await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - const receipt = await tx.wait() - assert.equal(0, receipt.logs.length) - }) - }) - - describe('#acceptPayeeship', () => { - beforeEach(async () => { - await registry - .connect(payee1) - .transferPayeeship( - await keeper1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('reverts when called by anyone but the proposed payee', async () => { - await evmRevert( - registry.connect(payee1).acceptPayeeship(await keeper1.getAddress()), - 'OnlyCallableByProposedPayee()', - ) - }) - - it('emits an event announcing the new payee', async () => { - const tx = await registry - .connect(payee2) - .acceptPayeeship(await keeper1.getAddress()) - await expect(tx) - .to.emit(registry, 'PayeeshipTransferred') - .withArgs( - await keeper1.getAddress(), - await payee1.getAddress(), - await payee2.getAddress(), - ) - }) - - it('does change the payee', async () => { - await registry.connect(payee2).acceptPayeeship(await keeper1.getAddress()) - - const info = await registry.getTransmitterInfo(await keeper1.getAddress()) - assert.equal(await payee2.getAddress(), info.payee) - }) - }) - - describe('#pause', () => { - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).pause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as paused', async () => { - assert.isFalse((await registry.getState()).state.paused) - - await registry.connect(owner).pause() - - assert.isTrue((await registry.getState()).state.paused) - }) - - it('Does not allow transmits when paused', async () => { - await registry.connect(owner).pause() - - await evmRevert( - getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1), - 'RegistryPaused()', - ) - }) - - it('Does not allow creation of new upkeeps when paused', async () => { - await registry.connect(owner).pause() - - await evmRevert( - registry - .connect(owner) - .registerUpkeep( - mock.address, - executeGas, - await admin.getAddress(), - emptyBytes, - emptyBytes, - ), - 'RegistryPaused()', - ) - }) - }) - - describe('#unpause', () => { - beforeEach(async () => { - await registry.connect(owner).pause() - }) - - it('reverts if called by a non-owner', async () => { - await evmRevert( - registry.connect(keeper1).unpause(), - 'Only callable by owner', - ) - }) - - it('marks the contract as not paused', async () => { - assert.isTrue((await registry.getState()).state.paused) - - await registry.connect(owner).unpause() - - assert.isFalse((await registry.getState()).state.paused) - }) - }) - - describe('migrateUpkeeps() / #receiveUpkeeps()', async () => { - let registry2: KeeperRegistry - let registryLogic2: KeeperRegistryLogic - - beforeEach(async () => { - registryLogic2 = await keeperRegistryLogicFactory - .connect(owner) - .deploy( - Mode.DEFAULT, - linkToken.address, - linkEthFeed.address, - gasPriceFeed.address, - ) - - const config = { - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - } - registry2 = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic2.address) - await registry2 - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - 1, - '0x', - ) - }) - - context('when permissions are set', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - }) - - it('migrates an upkeep', async () => { - expect((await registry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - // Set an upkeep admin transfer in progress too - await registry - .connect(admin) - .transferUpkeepAdmin(upkeepId, await payee1.getAddress()) - - // migrate - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], registry2.address) - expect((await registry.getState()).state.numUpkeeps).to.equal(0) - expect((await registry2.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') - expect((await registry2.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry2.getState()).state.expectedLinkBalance).to.equal( - toWei('100'), - ) - expect((await registry2.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - // migration will delete the upkeep and nullify admin transfer - await expect( - registry.connect(payee1).acceptUpkeepAdmin(upkeepId), - ).to.be.revertedWith('UpkeepCancelled()') - await expect( - registry2.connect(payee1).acceptUpkeepAdmin(upkeepId), - ).to.be.revertedWith('OnlyCallableByProposedAdmin()') - }) - - it('migrates a paused upkeep', async () => { - expect((await registry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - await registry.connect(admin).pauseUpkeep(upkeepId) - // verify the upkeep is paused - expect((await registry.getUpkeep(upkeepId)).paused).to.equal(true) - // migrate - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], registry2.address) - expect((await registry.getState()).state.numUpkeeps).to.equal(0) - expect((await registry2.getState()).state.numUpkeeps).to.equal(1) - expect((await registry.getUpkeep(upkeepId)).balance).to.equal(0) - expect((await registry2.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal('0x') - expect((await registry2.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry2.getState()).state.expectedLinkBalance).to.equal( - toWei('100'), - ) - // verify the upkeep is still paused after migration - expect((await registry2.getUpkeep(upkeepId)).paused).to.equal(true) - }) - - it('emits an event on both contracts', async () => { - expect((await registry.getUpkeep(upkeepId)).balance).to.equal( - toWei('100'), - ) - expect((await registry.getUpkeep(upkeepId)).checkData).to.equal( - randomBytes, - ) - expect((await registry.getState()).state.numUpkeeps).to.equal(1) - const tx = registry - .connect(admin) - .migrateUpkeeps([upkeepId], registry2.address) - await expect(tx) - .to.emit(registry, 'UpkeepMigrated') - .withArgs(upkeepId, toWei('100'), registry2.address) - await expect(tx) - .to.emit(registry2, 'UpkeepReceived') - .withArgs(upkeepId, toWei('100'), registry.address) - }) - - it('is only migratable by the admin', async () => { - await expect( - registry.connect(owner).migrateUpkeeps([upkeepId], registry2.address), - ).to.be.revertedWith('OnlyCallableByAdmin()') - await registry - .connect(admin) - .migrateUpkeeps([upkeepId], registry2.address) - }) - }) - - context('when permissions are not set', () => { - it('reverts', async () => { - // no permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([upkeepId], registry2.address)).to - .be.reverted - // only outgoing permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 1) - await registry2.setPeerRegistryMigrationPermission(registry.address, 0) - await expect(registry.migrateUpkeeps([upkeepId], registry2.address)).to - .be.reverted - // only incoming permissions - await registry.setPeerRegistryMigrationPermission(registry2.address, 0) - await registry2.setPeerRegistryMigrationPermission(registry.address, 2) - await expect(registry.migrateUpkeeps([upkeepId], registry2.address)).to - .be.reverted - // permissions opposite direction - await registry.setPeerRegistryMigrationPermission(registry2.address, 2) - await registry2.setPeerRegistryMigrationPermission(registry.address, 1) - await expect(registry.migrateUpkeeps([upkeepId], registry2.address)).to - .be.reverted - }) - }) - }) - - describe('#setPayees', () => { - const IGNORE_ADDRESS = '0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF' - - beforeEach(async () => { - keeperAddresses = keeperAddresses.slice(0, 4) - signerAddresses = signerAddresses.slice(0, 4) - payees = payees.slice(0, 4) - - // Redeploy registry with zero address payees (non set) - registry = await keeperRegistryFactory - .connect(owner) - .deploy(registryLogic.address) - - await registry - .connect(owner) - .setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig(config), - offchainVersion, - offchainBytes, - ) - }) - - it('reverts when not called by the owner', async () => { - await evmRevert( - registry.connect(keeper1).setPayees([]), - 'Only callable by owner', - ) - }) - - it('reverts with different numbers of payees than transmitters', async () => { - // 4 transmitters are set, so exactly 4 payess should be added - await evmRevert( - registry.connect(owner).setPayees([await payee1.getAddress()]), - 'ParameterLengthError()', - ) - await evmRevert( - registry - .connect(owner) - .setPayees([ - await payee1.getAddress(), - await payee1.getAddress(), - await payee1.getAddress(), - await payee1.getAddress(), - await payee1.getAddress(), - ]), - 'ParameterLengthError()', - ) - }) - - it('reverts if the payee is the zero address', async () => { - await evmRevert( - registry - .connect(owner) - .setPayees([ - await payee1.getAddress(), - '0x0000000000000000000000000000000000000000', - await payee3.getAddress(), - await payee4.getAddress(), - ]), - 'InvalidPayee()', - ) - }) - - it('sets the payees when exisitng payees are zero address', async () => { - //Initial payees should be zero address - for (let i = 0; i < keeperAddresses.length; i++) { - const payee = (await registry.getTransmitterInfo(keeperAddresses[i])) - .payee - assert.equal(payee, zeroAddress) - } - - await registry.connect(owner).setPayees(payees) - - for (let i = 0; i < keeperAddresses.length; i++) { - const payee = (await registry.getTransmitterInfo(keeperAddresses[i])) - .payee - assert.equal(payee, payees[i]) - } - }) - - it('does not change the payee if IGNORE_ADDRESS is used as payee', async () => { - // Set initial payees - await registry.connect(owner).setPayees(payees) - - const newPayees = [ - await payee1.getAddress(), - IGNORE_ADDRESS, - await payee3.getAddress(), - await payee4.getAddress(), - ] - await registry.connect(owner).setPayees(newPayees) - - const ignored = await registry.getTransmitterInfo( - await keeper2.getAddress(), - ) - assert.equal(await payee2.getAddress(), ignored.payee) - assert.equal(true, ignored.active) - }) - - it('reverts if payee is non zero and owner tries to change payee', async () => { - // Set initial payees - await registry.connect(owner).setPayees(payees) - - const newPayees = [ - await payee1.getAddress(), - await owner.getAddress(), - await payee3.getAddress(), - await payee4.getAddress(), - ] - await evmRevert( - registry.connect(owner).setPayees(newPayees), - 'InvalidPayee()', - ) - }) - - it('emits events for every payee added and removed', async () => { - const tx = await registry.connect(owner).setPayees(payees) - await expect(tx) - .to.emit(registry, 'PayeesUpdated') - .withArgs(keeperAddresses, payees) - }) - }) - - describe('#cancelUpkeep', () => { - it('reverts if the ID is not valid', async () => { - await evmRevert( - registry.connect(owner).cancelUpkeep(upkeepId.add(1)), - 'CannotCancel()', - ) - }) - - it('reverts if called by a non-owner/non-admin', async () => { - await evmRevert( - registry.connect(keeper1).cancelUpkeep(upkeepId), - 'OnlyCallableByOwnerOrAdmin()', - ) - }) - - describe('when called by the owner', async () => { - it('sets the registration to invalid immediately', async () => { - const tx = await registry.connect(owner).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(upkeepId) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(owner).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs(upkeepId, BigNumber.from(receipt.blockNumber)) - }) - - it('immediately prevents upkeep', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - it('does not revert if reverts if called multiple times', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - await evmRevert( - registry.connect(owner).cancelUpkeep(upkeepId), - 'CannotCancel()', - ) - }) - - describe('when called by the owner when the admin has just canceled', () => { - let oldExpiration: BigNumber - - beforeEach(async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - const registration = await registry.getUpkeep(upkeepId) - oldExpiration = registration.maxValidBlocknumber - }) - - it('allows the owner to cancel it more quickly', async () => { - await registry.connect(owner).cancelUpkeep(upkeepId) - - const registration = await registry.getUpkeep(upkeepId) - const newExpiration = registration.maxValidBlocknumber - assert.isTrue(newExpiration.lt(oldExpiration)) - }) - }) - }) - - describe('when called by the admin', async () => { - it('reverts if called again by the admin', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - await evmRevert( - registry.connect(admin).cancelUpkeep(upkeepId), - 'CannotCancel()', - ) - }) - - it('reverts if called by the owner after the timeout', async () => { - await registry.connect(admin).cancelUpkeep(upkeepId) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - await evmRevert( - registry.connect(owner).cancelUpkeep(upkeepId), - 'CannotCancel()', - ) - }) - - it('sets the registration to invalid in 50 blocks', async () => { - const tx = await registry.connect(admin).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - const registration = await registry.getUpkeep(upkeepId) - assert.equal( - registration.maxValidBlocknumber.toNumber(), - receipt.blockNumber + 50, - ) - }) - - it('emits an event', async () => { - const tx = await registry.connect(admin).cancelUpkeep(upkeepId) - const receipt = await tx.wait() - await expect(tx) - .to.emit(registry, 'UpkeepCanceled') - .withArgs( - upkeepId, - BigNumber.from(receipt.blockNumber + cancellationDelay), - ) - }) - - it('immediately prevents upkeep', async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await registry.connect(admin).cancelUpkeep(upkeepId) - - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - - for (let i = 0; i < cancellationDelay; i++) { - await ethers.provider.send('evm_mine', []) - } - - const tx = await getTransmitTx( - registry, - keeper1, - [upkeepId.toString()], - f + 1, - ) - - const receipt = await tx.wait() - const cancelledUpkeepReportLogs = - parseCancelledUpkeepReportLogs(receipt) - // exactly 1 CancelledUpkeepReport log should be emitted - assert.equal(cancelledUpkeepReportLogs.length, 1) - }) - - describe('when an upkeep has been performed', async () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - }) - - it('deducts a cancellation fee from the upkeep and gives to owner', async () => { - const minUpkeepSpend = toWei('10') - - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - const amountSpent = toWei('100').sub(upkeepBefore) - const cancellationFee = minUpkeepSpend.sub(amountSpent) - - await registry.connect(admin).cancelUpkeep(upkeepId) - - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // post upkeep balance should be previous balance minus cancellation fee - assert.isTrue(upkeepBefore.sub(cancellationFee).eq(upkeepAfter)) - // payee balance should not change - assert.isTrue(payee1Before.eq(payee1After)) - // owner should receive the cancellation fee - assert.isTrue(ownerAfter.sub(ownerBefore).eq(cancellationFee)) - }) - - it('deducts up to balance as cancellation fee', async () => { - // Very high min spend, should deduct whole balance as cancellation fees - const minUpkeepSpend = toWei('1000') - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - await registry.connect(admin).cancelUpkeep(upkeepId) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - - // all upkeep balance is deducted for cancellation fee - assert.equal(0, upkeepAfter.toNumber()) - // payee balance should not change - assert.isTrue(payee1After.eq(payee1Before)) - // all upkeep balance is transferred to the owner - assert.isTrue(ownerAfter.sub(ownerBefore).eq(upkeepBefore)) - }) - - it('does not deduct cancellation fee if more than minUpkeepSpend is spent', async () => { - // Very low min spend, already spent in one perform upkeep - const minUpkeepSpend = BigNumber.from(420) - await registry.connect(owner).setConfig( - signerAddresses, - keeperAddresses, - f, - encodeConfig({ - paymentPremiumPPB, - flatFeeMicroLink, - checkGasLimit, - stalenessSeconds, - gasCeilingMultiplier, - minUpkeepSpend, - maxCheckDataSize, - maxPerformDataSize, - maxPerformGas, - fallbackGasPrice, - fallbackLinkPrice, - transcoder: transcoder.address, - registrar: ethers.constants.AddressZero, - }), - offchainVersion, - offchainBytes, - ) - const payee1Before = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const upkeepBefore = (await registry.getUpkeep(upkeepId)).balance - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - await registry.connect(admin).cancelUpkeep(upkeepId) - const payee1After = await linkToken.balanceOf( - await payee1.getAddress(), - ) - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - const upkeepAfter = (await registry.getUpkeep(upkeepId)).balance - - // upkeep does not pay cancellation fee after cancellation because minimum upkeep spent is met - assert.isTrue(upkeepBefore.eq(upkeepAfter)) - // owner balance does not change - assert.isTrue(ownerAfter.eq(ownerBefore)) - // payee balance does not change - assert.isTrue(payee1Before.eq(payee1After)) - }) - }) - }) - }) - - describe('#withdrawPayment', () => { - beforeEach(async () => { - await linkToken.connect(owner).approve(registry.address, toWei('100')) - await registry.connect(owner).addFunds(upkeepId, toWei('100')) - await getTransmitTx(registry, keeper1, [upkeepId.toString()], f + 1) - }) - - it('reverts if called by anyone but the payee', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ), - 'OnlyCallableByPayee()', - ) - }) - - it('reverts if called with the 0 address', async () => { - await evmRevert( - registry - .connect(payee2) - .withdrawPayment(await keeper1.getAddress(), zeroAddress), - 'InvalidRecipient()', - ) - }) - - it('updates the balances', async () => { - const to = await nonkeeper.getAddress() - const keeperBefore = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationBefore = (await registry.getUpkeep(upkeepId)).balance - const toLinkBefore = await linkToken.balanceOf(to) - const registryLinkBefore = await linkToken.balanceOf(registry.address) - const registryPremiumBefore = (await registry.getState()).state - .totalPremium - const ownerBefore = (await registry.getState()).state.ownerLinkBalance - - // Withdrawing for first time, last collected = 0 - assert.equal(keeperBefore.lastCollected.toString(), '0') - - //// Do the thing - await registry - .connect(payee1) - .withdrawPayment(await keeper1.getAddress(), to) - - const keeperAfter = await registry.getTransmitterInfo( - await keeper1.getAddress(), - ) - const registrationAfter = (await registry.getUpkeep(upkeepId)).balance - const toLinkAfter = await linkToken.balanceOf(to) - const registryLinkAfter = await linkToken.balanceOf(registry.address) - const registryPremiumAfter = (await registry.getState()).state - .totalPremium - const ownerAfter = (await registry.getState()).state.ownerLinkBalance - - // registry total premium should not change - assert.isTrue(registryPremiumBefore.eq(registryPremiumAfter)) - // Last collected should be updated - assert.equal( - keeperAfter.lastCollected.toString(), - registryPremiumBefore.toString(), - ) - - const spareChange = registryPremiumBefore.mod( - BigNumber.from(keeperAddresses.length), - ) - // spare change should go to owner - assert.isTrue(ownerAfter.sub(spareChange).eq(ownerBefore)) - - assert.isTrue(keeperAfter.balance.eq(BigNumber.from(0))) - assert.isTrue(registrationBefore.eq(registrationAfter)) - assert.isTrue(toLinkBefore.add(keeperBefore.balance).eq(toLinkAfter)) - assert.isTrue( - registryLinkBefore.sub(keeperBefore.balance).eq(registryLinkAfter), - ) - }) - - it('emits a log announcing the withdrawal', async () => { - const balance = ( - await registry.getTransmitterInfo(await keeper1.getAddress()) - ).balance - const tx = await registry - .connect(payee1) - .withdrawPayment( - await keeper1.getAddress(), - await nonkeeper.getAddress(), - ) - await expect(tx) - .to.emit(registry, 'PaymentWithdrawn') - .withArgs( - await keeper1.getAddress(), - balance, - await nonkeeper.getAddress(), - await payee1.getAddress(), - ) - }) - }) -}) diff --git a/contracts/test/v0.8/dev/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts b/contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts similarity index 100% rename from contracts/test/v0.8/dev/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts rename to contracts/test/v0.8/automation/KeeperRegistryCheckUpkeepGasUsageWrapper.test.ts diff --git a/contracts/test/v0.8/functions/v1/Functions.test.ts b/contracts/test/v0.8/functions/v1/Functions.test.ts deleted file mode 100644 index 14a68c211b9..00000000000 --- a/contracts/test/v0.8/functions/v1/Functions.test.ts +++ /dev/null @@ -1,172 +0,0 @@ -import { ethers } from 'hardhat' -import { - publicAbi, - decodeDietCBOR, - hexToBuf, -} from '../../../test-helpers/helpers' -import { assert, expect } from 'chai' -import { Contract, ContractFactory, providers, Signer } from 'ethers' -import { Roles, getUsers } from '../../../test-helpers/setup' -import { makeDebug } from '../../../test-helpers/debug' - -const debug = makeDebug('FunctionsTestHelper') -let concreteFunctionsTestHelperFactory: ContractFactory - -let roles: Roles - -before(async () => { - roles = (await getUsers()).roles - concreteFunctionsTestHelperFactory = await ethers.getContractFactory( - 'src/v0.8/functions/tests/v1_X/testhelpers/FunctionsTestHelper.sol:FunctionsTestHelper', - roles.defaultAccount, - ) -}) - -describe('FunctionsTestHelper', () => { - let ctr: Contract - let defaultAccount: Signer - - beforeEach(async () => { - defaultAccount = roles.defaultAccount - ctr = await concreteFunctionsTestHelperFactory - .connect(defaultAccount) - .deploy() - }) - - it('has a limited public interface [ @skip-coverage ]', () => { - expect( - publicAbi(ctr, [ - 'closeEvent', - 'initializeRequestForInlineJavaScript', - 'addSecretsReference', - 'addTwoArgs', - 'addEmptyArgs', - ]), - ).to.equal(true) - }) - - async function parseRequestDataEvent(tx: providers.TransactionResponse) { - const receipt = await tx.wait() - const data = receipt.logs?.[0].data - const d = debug.extend('parseRequestDataEvent') - d('data %s', data) - return ethers.utils.defaultAbiCoder.decode(['bytes'], data ?? '') - } - - describe('#closeEvent', () => { - it('handles empty request', async () => { - const tx = await ctr.closeEvent() - const [payload] = await parseRequestDataEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual( - { - ...decoded, - language: decoded.language.toNumber(), - codeLocation: decoded.codeLocation.toNumber(), - }, - { - language: 0, - codeLocation: 0, - source: '', - }, - ) - }) - }) - - describe('#initializeRequestForInlineJavaScript', () => { - it('emits simple CBOR encoded request for js', async () => { - const js = 'function run(args, responses) {}' - await ctr.initializeRequestForInlineJavaScript(js) - const tx = await ctr.closeEvent() - const [payload] = await parseRequestDataEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual( - { - ...decoded, - language: decoded.language.toNumber(), - codeLocation: decoded.codeLocation.toNumber(), - }, - { - language: 0, - codeLocation: 0, - source: js, - }, - ) - }) - }) - - describe('#initializeRequestForInlineJavaScript to revert', () => { - it('reverts with EmptySource() if source param is empty', async () => { - await expect( - ctr.initializeRequestForInlineJavaScript(''), - ).to.be.revertedWith('EmptySource()') - }) - }) - - describe('#addSecrets', () => { - it('emits CBOR encoded request with js and secrets', async () => { - const js = 'function run(args, responses) {}' - const secrets = '0xA161616162' - await ctr.initializeRequestForInlineJavaScript(js) - await ctr.addSecretsReference(secrets) - const tx = await ctr.closeEvent() - const [payload] = await parseRequestDataEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual( - { - ...decoded, - language: decoded.language.toNumber(), - codeLocation: decoded.codeLocation.toNumber(), - secretsLocation: decoded.secretsLocation.toNumber(), - }, - { - language: 0, - codeLocation: 0, - source: js, - secretsLocation: 1, - secrets: hexToBuf(secrets), - }, - ) - }) - }) - - describe('#addSecrets to revert', () => { - it('reverts with EmptySecrets() if secrets param is empty', async () => { - const js = 'function run(args, responses) {}' - await ctr.initializeRequestForInlineJavaScript(js) - await expect(ctr.addSecretsReference('0x')).to.be.revertedWith( - 'EmptySecrets()', - ) - }) - }) - - describe('#addArgs', () => { - it('emits CBOR encoded request with js and args', async () => { - const js = 'function run(args, responses) {}' - await ctr.initializeRequestForInlineJavaScript(js) - await ctr.addTwoArgs('arg1', 'arg2') - const tx = await ctr.closeEvent() - const [payload] = await parseRequestDataEvent(tx) - const decoded = await decodeDietCBOR(payload) - assert.deepEqual( - { - ...decoded, - language: decoded.language.toNumber(), - codeLocation: decoded.codeLocation.toNumber(), - }, - { - language: 0, - codeLocation: 0, - source: js, - args: ['arg1', 'arg2'], - }, - ) - }) - }) - - describe('#addEmptyArgs to revert', () => { - it('reverts with EmptyArgs() if args param is empty', async () => { - await expect(ctr.addEmptyArgs()).to.be.revertedWith('EmptyArgs()') - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/FunctionsClient.test.ts b/contracts/test/v0.8/functions/v1/FunctionsClient.test.ts deleted file mode 100644 index 826953fb2c4..00000000000 --- a/contracts/test/v0.8/functions/v1/FunctionsClient.test.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { ethers } from 'hardhat' -import { assert, expect } from 'chai' -import { decodeDietCBOR, stringToBytes } from '../../../test-helpers/helpers' -import { - getSetupFactory, - FunctionsContracts, - FunctionsRoles, - anyValue, - ids, - createSubscription, - getEventArg, - parseOracleRequestEventArgs, - encodeReport, -} from './utils' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -describe('Functions Client', () => { - describe('#sendSimpleRequestWithJavaScript', () => { - it('emits events from the client and the oracle contracts', async () => { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - const flags = - '0x0101010101010101010101010101010101010101010101010101010101010101' - const callbackGas = 100_000 - await contracts.router.setFlags(subscriptionId, flags) - const defaultAccountAddress = await roles.defaultAccount.getAddress() - await expect( - contracts.client - .connect(roles.defaultAccount) - .sendSimpleRequestWithJavaScript( - 'return `hello world`', - subscriptionId, - ids.donId, - callbackGas, - ), - ) - .to.emit(contracts.client, 'RequestSent') - .withArgs(anyValue) - .to.emit(contracts.coordinator, 'OracleRequest') - .withArgs( - anyValue, - contracts.client.address, - defaultAccountAddress, - subscriptionId, - roles.subOwnerAddress, - anyValue, - anyValue, - flags, - callbackGas, - anyValue, - ) - }) - - it('respects gas flag setting', async () => { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - const flags = - '0x0101010101010101010101010101010101010101010101010101010101010101' - await contracts.router.setFlags(subscriptionId, flags) - await expect( - contracts.client - .connect(roles.defaultAccount) - .sendSimpleRequestWithJavaScript( - 'return `hello world`', - subscriptionId, - ids.donId, - 400_000, - ), - ) - .to.emit(contracts.client, 'RequestSent') - .to.emit(contracts.coordinator, 'OracleRequest') - await expect( - contracts.client - .connect(roles.defaultAccount) - .sendSimpleRequestWithJavaScript( - 'return `hello world`', - subscriptionId, - ids.donId, - 600_000, // limit set by gas flag == 1 is 500_000 - ), - ).to.be.revertedWith('GasLimitTooBig(500000)') - }) - - it('encodes user request to CBOR', async () => { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - const js = 'function run(){return response}' - const tx = await contracts.client.sendSimpleRequestWithJavaScript( - js, - subscriptionId, - ids.donId, - 20_000, - ) - const args = await parseOracleRequestEventArgs(tx) - assert.equal(args.length, 5) - const decoded = await decodeDietCBOR(args[3]) - assert.deepEqual( - { - ...decoded, - language: decoded.language.toNumber(), - codeLocation: decoded.codeLocation.toNumber(), - }, - { - language: 0, - codeLocation: 0, - source: js, - }, - ) - }) - }) - - describe('#fulfillRequest', () => { - it('emits fulfillment events', async () => { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - const tx = await contracts.client.sendSimpleRequestWithJavaScript( - 'function run(){return response}', - subscriptionId, - ids.donId, - 20_000, - ) - const { events } = await tx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - await expect(tx) - .to.emit(contracts.client, 'RequestSent') - .withArgs(requestId) - - const response = stringToBytes('response') - const error = stringToBytes('') - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - stringToBytes(''), - ) - await expect(contracts.coordinator.callReport(report)) - .to.emit(contracts.coordinator, 'OracleResponse') - .withArgs(requestId, await roles.defaultAccount.getAddress()) - .to.emit(contracts.client, 'FulfillRequestInvoked') - .withArgs(requestId, response, error) - }) - }) -}) - -describe('Faulty Functions Client', () => { - it('can complete requests with an empty callback', async () => { - const clientWithEmptyCallbackTestHelperFactory = - await ethers.getContractFactory( - 'src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientWithEmptyCallback.sol:FunctionsClientWithEmptyCallback', - roles.consumer, - ) - - const clientWithEmptyCallback = - await clientWithEmptyCallbackTestHelperFactory - .connect(roles.consumer) - .deploy(contracts.router.address) - - const subscriptionId = await createSubscription( - roles.subOwner, - [clientWithEmptyCallback.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - const tx = await clientWithEmptyCallback.sendSimpleRequestWithJavaScript( - 'function run(){return response}', - subscriptionId, - ids.donId, - 20_000, - ) - const { events } = await tx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - await expect(tx) - .to.emit(clientWithEmptyCallback, 'RequestSent') - .withArgs(requestId) - - const response = stringToBytes('response') - const error = stringToBytes('') - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - stringToBytes(''), - ) - await expect(contracts.coordinator.callReport(report)) - .to.emit(contracts.coordinator, 'OracleResponse') - .withArgs(requestId, await roles.defaultAccount.getAddress()) - .to.emit(contracts.router, 'RequestProcessed') - }) -}) diff --git a/contracts/test/v0.8/functions/v1/FunctionsCoordinator.test.ts b/contracts/test/v0.8/functions/v1/FunctionsCoordinator.test.ts deleted file mode 100644 index 89444ca8661..00000000000 --- a/contracts/test/v0.8/functions/v1/FunctionsCoordinator.test.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { expect } from 'chai' -import { - getSetupFactory, - FunctionsContracts, - coordinatorConfig, - FunctionsRoles, -} from './utils' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -describe('Functions Coordinator', () => { - describe('Config', () => { - it('non-owner is unable to update config', async () => { - await expect( - contracts.coordinator - .connect(roles.stranger) - .updateConfig(coordinatorConfig), - ).to.be.revertedWith('Only callable by owner') - }) - - it('Owner can update config', async () => { - const beforeConfig = await contracts.coordinator.getConfig() - await expect( - contracts.coordinator.updateConfig({ - ...coordinatorConfig, - donFee: 10, - }), - ).to.emit(contracts.coordinator, 'ConfigUpdated') - const afterConfig = await contracts.coordinator.getConfig() - expect(beforeConfig).to.not.equal(afterConfig) - }) - - it('returns the config set', async () => { - const config = await contracts.coordinator - .connect(roles.stranger) - .getConfig() - await Promise.all( - Object.keys(coordinatorConfig).map((key) => - expect(config[key]).to.equal( - coordinatorConfig[key as keyof typeof coordinatorConfig], - ), - ), - ) - }) - - it('#fulfillmentGasPriceOverEstimationBP overestimates gas cost', async () => { - const estimateWithNoOverestimaton = - await contracts.coordinator.estimateCost(1, 0x0, 100_000, 2000000000) - - await contracts.coordinator.updateConfig({ - ...coordinatorConfig, - fulfillmentGasPriceOverEstimationBP: 10_000, - }) - - // Halve the gas price, which should be the same estimate because of fulfillmentGasPriceOverEstimationBP doubling the gas price - const estimateWithOverestimaton = - await contracts.coordinator.estimateCost(1, 0x0, 100_000, 1000000000) - - expect(estimateWithNoOverestimaton).to.equal(estimateWithOverestimaton) - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/FunctionsRouter.test.ts b/contracts/test/v0.8/functions/v1/FunctionsRouter.test.ts deleted file mode 100644 index e484283e80b..00000000000 --- a/contracts/test/v0.8/functions/v1/FunctionsRouter.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { expect } from 'chai' -import { ethers } from 'hardhat' -import { stringToBytes } from '../../../test-helpers/helpers' -import { - getSetupFactory, - FunctionsContracts, - functionsRouterConfig, - FunctionsRoles, -} from './utils' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -describe('Functions Router - Request lifecycle', () => { - describe('Config', () => { - it('#typeAndVersion', async () => { - expect(await contracts.router.typeAndVersion()).to.be.equal( - 'Functions Router v2.0.0', - ) - }) - it('non-owner is unable to update config', async () => { - await expect( - contracts.router - .connect(roles.stranger) - .updateConfig(functionsRouterConfig), - ).to.be.revertedWith('Only callable by owner') - }) - - it('owner can update config', async () => { - const beforeConfig = await contracts.router.getConfig() - await expect( - contracts.router.updateConfig({ - ...functionsRouterConfig, - adminFee: 10, - }), - ).to.emit(contracts.router, 'ConfigUpdated') - const afterConfig = await contracts.router.getConfig() - expect(beforeConfig).to.not.equal(afterConfig) - }) - - it('returns the config set', async () => { - const config = await contracts.router.connect(roles.stranger).getConfig() - await Promise.all( - Object.keys(functionsRouterConfig).map((key) => - expect(config[key]).to.deep.equal( - functionsRouterConfig[key as keyof typeof functionsRouterConfig], - ), - ), - ) - }) - }) - describe('Allow List path', () => { - it('non-owner is unable to set Allow List ID', async () => { - await expect( - contracts.router - .connect(roles.stranger) - .setAllowListId(ethers.utils.hexZeroPad(stringToBytes(''), 32)), - ).to.be.revertedWith('Only callable by owner') - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/FunctionsSubscriptions.test.ts b/contracts/test/v0.8/functions/v1/FunctionsSubscriptions.test.ts deleted file mode 100644 index 86cfb9dd5fc..00000000000 --- a/contracts/test/v0.8/functions/v1/FunctionsSubscriptions.test.ts +++ /dev/null @@ -1,862 +0,0 @@ -import { ethers } from 'hardhat' -import { expect } from 'chai' -import { BigNumber } from 'ethers' -import { randomAddressString } from 'hardhat/internal/hardhat-network/provider/utils/random' -import { - getSetupFactory, - FunctionsContracts, - FunctionsRoles, - createSubscription, - acceptTermsOfService, - ids, - getEventArg, - accessControlMockPrivateKey, - encodeReport, -} from './utils' -import { stringToBytes } from '../../../test-helpers/helpers' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -const donLabel = ethers.utils.formatBytes32String('1') - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -describe('Functions Router - Subscriptions', () => { - describe('Subscription management', () => { - describe('#createSubscription', async function () { - it('can create a subscription', async function () { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - await expect( - contracts.router.connect(roles.subOwner).createSubscription(), - ) - .to.emit(contracts.router, 'SubscriptionCreated') - .withArgs(1, roles.subOwnerAddress) - const s = await contracts.router.getSubscription(1) - expect(s.balance.toString()).to.equal('0') - expect(s.owner).to.equal(roles.subOwnerAddress) - }) - it('subscription id increments', async function () { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - await expect( - contracts.router.connect(roles.subOwner).createSubscription(), - ) - .to.emit(contracts.router, 'SubscriptionCreated') - .withArgs(1, roles.subOwnerAddress) - await expect( - contracts.router.connect(roles.subOwner).createSubscription(), - ) - .to.emit(contracts.router, 'SubscriptionCreated') - .withArgs(2, roles.subOwnerAddress) - }) - it('cannot create more than the max', async function () { - const subId = createSubscription( - roles.subOwner, - [], - contracts.router, - contracts.accessControl, - ) - for (let i = 0; i < 100; i++) { - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, randomAddressString()) - } - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, randomAddressString()), - ).to.be.revertedWith(`TooManyConsumers`) - }) - }) - - describe('#proposeSubscriptionOwnerTransfer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - it('rejects non-owner', async function () { - await expect( - contracts.router - .connect(roles.stranger) - .proposeSubscriptionOwnerTransfer(subId, roles.strangerAddress), - ).to.be.revertedWith(`MustBeSubscriptionOwner()`) - }) - it('owner can request transfer', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .proposeSubscriptionOwnerTransfer(subId, roles.strangerAddress), - ) - .to.emit(contracts.router, 'SubscriptionOwnerTransferRequested') - .withArgs(subId, roles.subOwnerAddress, roles.strangerAddress) - // Same request reverts - await expect( - contracts.router - .connect(roles.subOwner) - .proposeSubscriptionOwnerTransfer(subId, roles.strangerAddress), - ).to.be.revertedWith('InvalidCalldata') - }) - }) - - describe('#acceptSubscriptionOwnerTransfer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - it('subscription must exist', async function () { - // 0x0 is requested owner - await expect( - contracts.router - .connect(roles.subOwner) - .acceptSubscriptionOwnerTransfer(1203123123), - ).to.be.revertedWith(`MustBeProposedOwner`) - }) - it('must be requested owner to accept', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .proposeSubscriptionOwnerTransfer(subId, roles.strangerAddress), - ) - await expect( - contracts.router - .connect(roles.subOwner) - .acceptSubscriptionOwnerTransfer(subId), - ).to.be.revertedWith(`MustBeProposedOwner`) - }) - it('requested owner can accept', async function () { - await acceptTermsOfService( - contracts.accessControl, - roles.stranger, - roles.strangerAddress, - ) - await expect( - contracts.router - .connect(roles.subOwner) - .proposeSubscriptionOwnerTransfer(subId, roles.strangerAddress), - ) - .to.emit(contracts.router, 'SubscriptionOwnerTransferRequested') - .withArgs(subId, roles.subOwnerAddress, roles.strangerAddress) - await expect( - contracts.router - .connect(roles.stranger) - .acceptSubscriptionOwnerTransfer(subId), - ) - .to.emit(contracts.router, 'SubscriptionOwnerTransferred') - .withArgs(subId, roles.subOwnerAddress, roles.strangerAddress) - }) - }) - - describe('#addConsumer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - it('subscription must exist', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(1203123123, roles.strangerAddress), - ).to.be.revertedWith(`InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - contracts.router - .connect(roles.stranger) - .addConsumer(subId, roles.strangerAddress), - ).to.be.revertedWith(`MustBeSubscriptionOwner()`) - }) - it('add is idempotent', async function () { - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress) - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress), - ).to.not.be.reverted - }) - it('cannot add more than maximum', async function () { - // There is one consumer, add another 99 to hit the max - for (let i = 0; i < 99; i++) { - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, randomAddressString()) - } - // Adding one more should fail - // await contracts.router.connect(roles.subOwner).addConsumer(subId, roles.strangerAddress); - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress), - ).to.be.revertedWith(`TooManyConsumers`) - // Same is true if we first create with the maximum - const consumers: string[] = [] - for (let i = 0; i < 100; i++) { - consumers.push(randomAddressString()) - } - subId = await createSubscription( - roles.subOwner, - consumers, - contracts.router, - contracts.accessControl, - ) - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress), - ).to.be.revertedWith(`TooManyConsumers`) - }) - it('owner can update', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress), - ) - .to.emit(contracts.router, 'SubscriptionConsumerAdded') - .withArgs(subId, roles.strangerAddress) - }) - }) - - describe('#removeConsumer', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - it('subscription must exist', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .removeConsumer(1203123123, roles.strangerAddress), - ).to.be.revertedWith(`InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - contracts.router - .connect(roles.stranger) - .removeConsumer(subId, roles.strangerAddress), - ).to.be.revertedWith(`MustBeSubscriptionOwner()`) - }) - it('owner can update', async function () { - const subBefore = await contracts.router.getSubscription(subId) - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress) - await expect( - contracts.router - .connect(roles.subOwner) - .removeConsumer(subId, roles.strangerAddress), - ) - .to.emit(contracts.router, 'SubscriptionConsumerRemoved') - .withArgs(subId, roles.strangerAddress) - const subAfter = await contracts.router.getSubscription(subId) - // Subscription should NOT contain the removed consumer - expect(subBefore.consumers).to.deep.equal(subAfter.consumers) - }) - it('can remove all consumers', async function () { - // Testing the handling of zero. - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress) - await contracts.router - .connect(roles.subOwner) - .removeConsumer(subId, roles.strangerAddress) - await contracts.router - .connect(roles.subOwner) - .removeConsumer(subId, roles.consumerAddress) - // Should be empty - const subAfter = await contracts.router.getSubscription(subId) - expect(subAfter.consumers).to.deep.equal([]) - }) - }) - - describe('#pendingRequestExists', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('130790416713017745'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, contracts.client.address) - }) - it('returns false when there is no latest pending request', async function () { - expect( - await contracts.router - .connect(roles.subOwner) - .pendingRequestExists(subId), - ).to.be.false - }) - it('returns true when the latest request is pending', async function () { - await contracts.client - .connect(roles.consumer) - .sendSimpleRequestWithJavaScript( - `return 'hello world'`, - subId, - donLabel, - 20_000, - ) - expect( - await contracts.router - .connect(roles.subOwner) - .pendingRequestExists(subId), - ).to.be.true - }) - }) - - describe('#cancelSubscription', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - it('subscription must exist', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .cancelSubscription(1203123123, roles.subOwnerAddress), - ).to.be.revertedWith(`InvalidSubscription`) - }) - it('must be owner', async function () { - await expect( - contracts.router - .connect(roles.stranger) - .cancelSubscription(subId, roles.subOwnerAddress), - ).to.be.revertedWith(`MustBeSubscriptionOwner()`) - }) - it('can cancel', async function () { - const strangerBalanceBefore = await contracts.linkToken.balanceOf( - roles.strangerAddress, - ) - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('1000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await expect( - contracts.router - .connect(roles.subOwner) - .cancelSubscription(subId, roles.strangerAddress), - ) - .to.emit(contracts.router, 'SubscriptionCanceled') - .withArgs(subId, roles.strangerAddress, BigNumber.from('0')) - const strangerBalance = await contracts.linkToken.balanceOf( - roles.strangerAddress, - ) - expect(strangerBalance.toString()).to.equal( - strangerBalanceBefore.toString(), - ) - await expect( - contracts.router.connect(roles.subOwner).getSubscription(subId), - ).to.be.revertedWith('InvalidSubscription') - }) - it('can add same consumer after canceling', async function () { - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('1000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress) - await contracts.router - .connect(roles.subOwner) - .cancelSubscription(subId, roles.strangerAddress) - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - // The cancel should have removed this consumer, so we can add it again. - await expect( - contracts.router - .connect(roles.subOwner) - .addConsumer(subId, roles.strangerAddress), - ).to.not.be.reverted - }) - it('cannot cancel with pending request', async function () { - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('130790416713017745'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - await contracts.router - .connect(roles.subOwner) - .addConsumer(subId, contracts.client.address) - await contracts.client - .connect(roles.consumer) - .sendSimpleRequestWithJavaScript( - `return 'hello world'`, - subId, - donLabel, - 20_000, - ) - // Should revert with outstanding requests - await expect( - contracts.router - .connect(roles.subOwner) - .cancelSubscription(subId, roles.strangerAddress), - ).to.be.revertedWith('CannotRemoveWithPendingRequests()') - // However the owner is able to cancel - // funds go to the sub owner. - await expect( - contracts.router - .connect(roles.defaultAccount) - .ownerCancelSubscription(subId), - ) - .to.emit(contracts.router, 'SubscriptionCanceled') - .withArgs( - subId, - roles.subOwnerAddress, - BigNumber.from('130790416713017745'), - ) - }) - }) - - describe('#recoverFunds', async function () { - let subId: number - beforeEach(async () => { - subId = await createSubscription( - roles.subOwner, - [roles.consumerAddress], - contracts.router, - contracts.accessControl, - ) - }) - - it('function that should change internal balance do', async function () { - type bf = [() => Promise, BigNumber] - const balanceChangingFns: Array = [ - [ - async function () { - const s = ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]) - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('1000'), - s, - ) - }, - BigNumber.from('1000'), - ], - [ - async function () { - await contracts.router - .connect(roles.subOwner) - .cancelSubscription(subId, roles.strangerAddress) - }, - BigNumber.from('0'), - ], - ] - for (const [fn, expectedBalanceChange] of balanceChangingFns) { - const startingBalance = await contracts.router.getTotalBalance() - await fn() - const endingBalance = await contracts.router.getTotalBalance() - expect(endingBalance.sub(startingBalance.toString())).to.equal( - expectedBalanceChange.toString(), - ) - } - }) - it('only owner can recover', async function () { - await expect( - contracts.router - .connect(roles.subOwner) - .recoverFunds(roles.strangerAddress), - ).to.be.revertedWith('Only callable by owner') - }) - - it('owner can recover link transferred', async function () { - // Set the internal balance - expect( - await contracts.linkToken.balanceOf(roles.strangerAddress), - ).to.equal(BigNumber.from('1000000000000000000')) - const subscription = ethers.utils.defaultAbiCoder.encode( - ['uint64'], - [subId], - ) - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('1000'), - subscription, - ) - // Circumvent internal balance - await contracts.linkToken - .connect(roles.subOwner) - .transfer(contracts.router.address, BigNumber.from('1000')) - // Should recover this 1000 - await expect( - contracts.router - .connect(roles.defaultAccount) - .recoverFunds(roles.strangerAddress), - ) - .to.emit(contracts.router, 'FundsRecovered') - .withArgs(roles.strangerAddress, BigNumber.from('1000')) - expect( - await contracts.linkToken.balanceOf(roles.strangerAddress), - ).to.equal(BigNumber.from('1000000000000001000')) - }) - }) - }) - - describe('#oracleWithdraw', async function () { - it('cannot withdraw with no balance', async function () { - await expect( - contracts.router - .connect(roles.oracleNode) - .oracleWithdraw(randomAddressString(), BigNumber.from('100')), - ).to.be.revertedWith(`InsufficientBalance`) - }) - }) - - describe('#ownerWithdraw', async function () { - it('cannot withdraw more than balance', async function () { - await expect( - contracts.router.oracleWithdraw( - randomAddressString(), - BigNumber.from('100'), - ), - ).to.be.revertedWith(`InsufficientBalance`) - }) - }) - - describe('#flagsSet', async function () { - it('get flags that were previously set', async function () { - const flags = ethers.utils.formatBytes32String('arbitrary_byte_values') - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - await expect( - contracts.router.connect(roles.subOwner).createSubscription(), - ) - .to.emit(contracts.router, 'SubscriptionCreated') - .withArgs(1, roles.subOwnerAddress) - await contracts.router.setFlags(1, flags) - expect(await contracts.router.getFlags(1)).to.equal(flags) - }) - }) - - describe('#reentrancy', async function () { - // Use a fixed gas price for these tests - const gasPrice = 3000000000 // 3 gwei - - it('allows callbacks to start another request if they have sufficient funds', async function () { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - - // Set test helper flag - await contracts.client.setDoValidReentrantOperation( - true, - subscriptionId, - ids.donId, - ) - - // Set flag so they have enough callback gas - const flags = new Uint8Array(32) - flags[0] = 1 - await contracts.router - .connect(roles.defaultAccount) - .setFlags(subscriptionId, flags) - - // Send request - const tx = await contracts.client.sendSimpleRequestWithJavaScript( - 'function run(){return response}', - subscriptionId, - ids.donId, - 400_000, - { gasPrice }, - ) - const { events } = await tx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - await expect(tx) - .to.emit(contracts.client, 'RequestSent') - .withArgs(requestId) - - const response = stringToBytes('response') - const error = stringToBytes('') - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const offchainMetadata = stringToBytes('') - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - offchainMetadata, - ) - - await expect(contracts.coordinator.callReport(report, { gasPrice })) - .to.emit(contracts.coordinator, 'OracleResponse') - .withArgs(requestId, await roles.defaultAccount.getAddress()) - .to.emit(contracts.router, 'RequestProcessed') - .withArgs( - requestId, - subscriptionId, - () => true, - () => true, - 0, // Result code for callback failing - () => true, - () => true, - () => true, - ) - .to.emit(contracts.client, 'FulfillRequestInvoked') - .withArgs(requestId, response, error) - .to.emit(contracts.client, 'SendRequestInvoked') - }) - - it('prevents callbacks from starting another request if have insufficient funds', async function () { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - const createSubTx = await contracts.router - .connect(roles.subOwner) - .createSubscription() - const createSubReceipt = await createSubTx.wait() - const subscriptionId = - createSubReceipt.events[0].args['subscriptionId'].toNumber() - await contracts.router - .connect(roles.subOwner) - .addConsumer(subscriptionId, contracts.client.address) - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('300000000000000000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subscriptionId]), - ) - - // Set test helper flag - await contracts.client.setDoValidReentrantOperation( - true, - subscriptionId, - ids.donId, - ) - - // Set flag so they have enough callback gas - const flags = new Uint8Array(32) - flags[0] = 1 - await contracts.router - .connect(roles.defaultAccount) - .setFlags(subscriptionId, flags) - - // Send request - const tx = await contracts.client.sendSimpleRequestWithJavaScript( - 'function run(){return response}', - subscriptionId, - ids.donId, - 400_000, - { gasPrice }, - ) - const { events } = await tx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - await expect(tx) - .to.emit(contracts.client, 'RequestSent') - .withArgs(requestId) - - const response = stringToBytes('response') - const error = stringToBytes('') - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const offchainMetadata = stringToBytes('') - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - offchainMetadata, - ) - - await expect(contracts.coordinator.callReport(report, { gasPrice })) - .to.emit(contracts.coordinator, 'OracleResponse') - .withArgs(requestId, await roles.defaultAccount.getAddress()) - .to.emit(contracts.client, 'FulfillRequestInvoked') - .withArgs(requestId, response, error) - .to.emit(contracts.router, 'RequestProcessed') - .withArgs( - requestId, - subscriptionId, - () => true, - () => true, - 1, // Result code for callback failing - () => true, - () => true, - () => true, - ) - }) - - it('callbacks are unable to improperly use subscription methods', async function () { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - const createSubTx = await contracts.router - .connect(roles.subOwner) - .createSubscription() - const createSubReceipt = await createSubTx.wait() - const subscriptionId = - createSubReceipt.events[0].args['subscriptionId'].toNumber() - await contracts.router - .connect(roles.subOwner) - .addConsumer(subscriptionId, contracts.client.address) - await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('1000000000000000000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subscriptionId]), - ) - - // Set flag so they have enough callback gas - const flags = new Uint8Array(32) - flags[0] = 1 - await contracts.router - .connect(roles.defaultAccount) - .setFlags(subscriptionId, flags) - - // Accept ToS for client contract - const acceptorAddress = roles.subOwnerAddress - const recipientAddress = contracts.client.address - const message = await contracts.accessControl.getMessage( - acceptorAddress, - recipientAddress, - ) - const wallet = new ethers.Wallet(accessControlMockPrivateKey) - const flatSignature = await wallet.signMessage( - ethers.utils.arrayify(message), - ) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - await contracts.client - .connect(roles.subOwner) - .acceptTermsOfService(acceptorAddress, recipientAddress, r, s, v) - - // Transfer Subscription ownership to client contract so that it can call subscription methods - await contracts.router - .connect(roles.subOwner) - .proposeSubscriptionOwnerTransfer( - subscriptionId, - contracts.client.address, - ) - await contracts.client.acceptSubscriptionOwnerTransfer(subscriptionId) - - // Set test helper flag - await contracts.client.setDoInvalidReentrantOperation( - true, - subscriptionId, - ) - - // Send request - const tx = await contracts.client.sendSimpleRequestWithJavaScript( - 'function run(){return response}', - subscriptionId, - ids.donId, - 400_000, - { gasPrice }, - ) - const { events } = await tx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - await expect(tx) - .to.emit(contracts.client, 'RequestSent') - .withArgs(requestId) - - const response = stringToBytes('response') - const error = stringToBytes('') - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const offchainMetadata = stringToBytes('') - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - offchainMetadata, - ) - - await expect(contracts.coordinator.callReport(report, { gasPrice })) - .to.emit(contracts.coordinator, 'OracleResponse') - .withArgs(requestId, await roles.defaultAccount.getAddress()) - .to.emit(contracts.client, 'FulfillRequestInvoked') - .withArgs(requestId, response, error) - .to.emit(contracts.router, 'RequestProcessed') - .withArgs( - requestId, - subscriptionId, - () => true, - () => true, - 1, // Result code for callback failing - () => true, - () => true, - () => true, - ) - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/GasGolf.test.ts b/contracts/test/v0.8/functions/v1/GasGolf.test.ts deleted file mode 100644 index 32cc660beda..00000000000 --- a/contracts/test/v0.8/functions/v1/GasGolf.test.ts +++ /dev/null @@ -1,116 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber } from 'ethers' -import { - accessControlMockPrivateKey, - encodeReport, - FunctionsContracts, - FunctionsRoles, - getEventArg, - getSetupFactory, - ids, -} from './utils' -import { stringToBytes } from '../../../test-helpers/helpers' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -const baselineGasUsed = 721271 -let currentGasUsed = 0 - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -after(() => { - const score = currentGasUsed - baselineGasUsed - console.log(`\n ⛳ Par : ${baselineGasUsed} gas`) - console.log(`\n 🏌️ You : ${currentGasUsed} gas`) - console.log(`\n 🚩 Score : ${score} gas`) -}) - -describe('Gas Golf', () => { - it('taking a swing', async () => { - // User signs Terms of Service - const message = await contracts.accessControl.getMessage( - roles.consumerAddress, - roles.consumerAddress, - ) - const wallet = new ethers.Wallet(accessControlMockPrivateKey) - const flatSignature = await wallet.signMessage( - ethers.utils.arrayify(message), - ) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - const acceptTermsOfServiceTx = await contracts.accessControl - .connect(roles.consumer) - .acceptTermsOfService( - roles.consumerAddress, - roles.consumerAddress, - r, - s, - v, - ) - const { gasUsed: acceptTermsOfServiceGasUsed } = - await acceptTermsOfServiceTx.wait() - - // User creates a new Subscription - const createSubscriptionTx = await contracts.router - .connect(roles.consumer) - .createSubscription() - const createSubscriptionTxReceipt = await createSubscriptionTx.wait() - const createSubscriptionTxGasUsed = createSubscriptionTxReceipt.gasUsed - const subscriptionId = - createSubscriptionTxReceipt.events[0].args['subscriptionId'].toNumber() - - // User adds a consuming contract to their Subscription - const addConsumerTx = await contracts.router - .connect(roles.consumer) - .addConsumer(subscriptionId, contracts.client.address) - const { gasUsed: addConsumerTxGasUsed } = await addConsumerTx.wait() - - // User funds their subscription - const transferAndCallTx = await contracts.linkToken - .connect(roles.subOwner) - .transferAndCall( - contracts.router.address, - BigNumber.from('54666805176129187'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subscriptionId]), - ) - const { gasUsed: transferAndCallTxGasUsed } = await transferAndCallTx.wait() - - // User sends request - const requestTx = await contracts.client.sendSimpleRequestWithJavaScript( - 'function myFancyFunction(){return "woah, thats fancy"}', - subscriptionId, - ids.donId, - 20_000, - ) - const { gasUsed: requestTxGasUsed, events } = await requestTx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - const oracleRequestEvent = await contracts.coordinator.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - // DON's transmitter submits a response - const response = stringToBytes('woah, thats fancy') - const error = stringToBytes('') - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const offchainMetadata = stringToBytes('') - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - response, - error, - onchainMetadata, - offchainMetadata, - ) - const fulfillmentTx = await contracts.coordinator.callReport(report) - const { gasUsed: fulfillmentTxGasUsed } = await fulfillmentTx.wait() - - currentGasUsed = acceptTermsOfServiceGasUsed - .add(createSubscriptionTxGasUsed) - .add(addConsumerTxGasUsed) - .add(transferAndCallTxGasUsed) - .add(requestTxGasUsed) - .add(fulfillmentTxGasUsed) - .toNumber() - }) -}) diff --git a/contracts/test/v0.8/functions/v1/RouterBase.test.ts b/contracts/test/v0.8/functions/v1/RouterBase.test.ts deleted file mode 100644 index 92f9c7d320b..00000000000 --- a/contracts/test/v0.8/functions/v1/RouterBase.test.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { ethers } from 'hardhat' -import { expect } from 'chai' -import { - getSetupFactory, - coordinatorConfig, - FunctionsContracts, - FunctionsFactories, - FunctionsRoles, - ids, - createSubscription, - encodeReport, - stringToHex, - getEventArg, -} from './utils' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let factories: FunctionsFactories -let roles: FunctionsRoles - -beforeEach(async () => { - ;({ contracts, factories, roles } = setup()) -}) - -describe('FunctionsRouter - Base', () => { - describe('Updates', () => { - it('One or more contracts on a route can be updated by the owner', async () => { - const coordinator2 = await factories.functionsCoordinatorFactory - .connect(roles.defaultAccount) - .deploy( - contracts.router.address, - coordinatorConfig, - contracts.mockLinkEth.address, - contracts.mockLinkUsd.address, - ) - const coordinator3 = await factories.functionsCoordinatorFactory - .connect(roles.defaultAccount) - .deploy( - contracts.router.address, - coordinatorConfig, - contracts.mockLinkEth.address, - contracts.mockLinkUsd.address, - ) - const coordinator4 = await factories.functionsCoordinatorFactory - .connect(roles.defaultAccount) - .deploy( - contracts.router.address, - coordinatorConfig, - contracts.mockLinkEth.address, - contracts.mockLinkUsd.address, - ) - - await expect( - contracts.router['getContractById(bytes32)'](ids.donId2), - ).to.be.revertedWith('RouteNotFound') - await expect( - contracts.router['getContractById(bytes32)'](ids.donId3), - ).to.be.revertedWith('RouteNotFound') - await expect( - contracts.router['getContractById(bytes32)'](ids.donId4), - ).to.be.revertedWith('RouteNotFound') - await expect( - contracts.router.proposeContractsUpdate( - [ids.donId2, ids.donId3, ids.donId4], - [coordinator2.address, coordinator3.address, coordinator4.address], - ), - ).to.emit(contracts.router, `ContractProposed`) - - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - - const requestProposedTx = await contracts.client.sendRequestProposed( - `return 'hello world'`, - subscriptionId, - ids.donId2, - ) - - const { events } = await requestProposedTx.wait() - const requestId = getEventArg(events, 'RequestSent', 0) - - const oracleRequestEvent = await coordinator2.queryFilter( - contracts.coordinator.filters.OracleRequest(), - ) - const onchainMetadata = oracleRequestEvent[0].args?.['commitment'] - const report = await encodeReport( - ethers.utils.hexZeroPad(requestId, 32), - stringToHex('hello world'), - stringToHex(''), - onchainMetadata, - stringToHex(''), - ) - - await expect( - coordinator2 - .connect(roles.oracleNode) - .callReport(report, { gasLimit: 500_000 }), - ).to.emit(contracts.client, 'FulfillRequestInvoked') - - await expect(contracts.router.updateContracts()).to.emit( - contracts.router, - 'ContractUpdated', - ) - expect( - await contracts.router['getContractById(bytes32)'](ids.donId2), - ).to.equal(coordinator2.address) - expect( - await contracts.router['getContractById(bytes32)'](ids.donId3), - ).to.equal(coordinator3.address) - expect( - await contracts.router['getContractById(bytes32)'](ids.donId4), - ).to.equal(coordinator4.address) - }) - - it('non-owner is unable to propose contract updates', async () => { - await expect( - contracts.router - .connect(roles.stranger) - .proposeContractsUpdate([ids.donId], [contracts.coordinator.address]), - ).to.be.revertedWith('Only callable by owner') - }) - - it('non-owner is unable to apply contract updates', async () => { - await expect( - contracts.router.connect(roles.stranger).updateContracts(), - ).to.be.revertedWith('Only callable by owner') - }) - }) - - describe('Emergency Pause', () => { - it('has paused state visible', async () => { - const paused = await contracts.router.paused() - expect(paused).to.equal(false) - }) - it('can pause the system', async () => { - const subscriptionId = await createSubscription( - roles.subOwner, - [contracts.client.address], - contracts.router, - contracts.accessControl, - contracts.linkToken, - ) - - await contracts.router.pause() - - await expect( - contracts.client.sendSimpleRequestWithJavaScript( - `return 'hello world'`, - subscriptionId, - ids.donId, - 20_000, - ), - ).to.be.revertedWith('Pausable: paused') - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/TermsOfServiceAllowList.test.ts b/contracts/test/v0.8/functions/v1/TermsOfServiceAllowList.test.ts deleted file mode 100644 index 1e1ad18a7d6..00000000000 --- a/contracts/test/v0.8/functions/v1/TermsOfServiceAllowList.test.ts +++ /dev/null @@ -1,166 +0,0 @@ -import { ethers } from 'hardhat' -import { expect } from 'chai' -import { - getSetupFactory, - FunctionsContracts, - FunctionsRoles, - acceptTermsOfService, - accessControlMockPrivateKey, - accessControlConfig, -} from './utils' - -const setup = getSetupFactory() -let contracts: FunctionsContracts -let roles: FunctionsRoles - -beforeEach(async () => { - ;({ contracts, roles } = setup()) -}) - -describe('ToS Access Control', () => { - describe('Config', () => { - it('non-owner is unable to update config', async () => { - await expect( - contracts.accessControl - .connect(roles.stranger) - .updateConfig(accessControlConfig), - ).to.be.revertedWith('Only callable by owner') - }) - - it('Owner can update config', async () => { - const beforeConfig = await contracts.accessControl.getConfig() - await expect( - contracts.accessControl.updateConfig({ - ...accessControlConfig, - enabled: false, - }), - ).to.emit(contracts.accessControl, 'ConfigUpdated') - const afterConfig = await contracts.accessControl.getConfig() - expect(beforeConfig).to.not.equal(afterConfig) - }) - it('returns the config set', async () => { - const config = await contracts.accessControl - .connect(roles.stranger) - .getConfig() - await Promise.all( - Object.keys(accessControlConfig).map((key) => { - expect(config[key]).to.equal( - accessControlConfig[key as keyof typeof accessControlConfig], - ) - }), - ) - }) - }) - - describe('Accepting', () => { - it('can only be done with a valid signature', async () => { - const message = await contracts.accessControl.getMessage( - roles.strangerAddress, - roles.strangerAddress, - ) - const flatSignature = await roles.stranger.signMessage( - ethers.utils.arrayify(message), - ) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - await expect( - contracts.accessControl - .connect(roles.stranger) - .acceptTermsOfService( - roles.strangerAddress, - roles.strangerAddress, - r, - s, - v, - ), - ).to.be.revertedWith('InvalidSignature') - }) - it('can be done by Externally Owned Accounts if recipient themself', async () => { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - expect( - await contracts.accessControl.hasAccess(roles.subOwnerAddress, '0x'), - ).to.equal(true) - }) - it('cannot be done by Externally Owned Accounts if recipient another EoA', async () => { - await expect( - acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.strangerAddress, - ), - ).to.be.revertedWith('InvalidUsage') - }) - it('can be done by Contract Accounts if recipient themself', async () => { - const acceptorAddress = roles.consumerAddress - const recipientAddress = contracts.client.address - const message = await contracts.accessControl.getMessage( - acceptorAddress, - recipientAddress, - ) - const wallet = new ethers.Wallet(accessControlMockPrivateKey) - const flatSignature = await wallet.signMessage( - ethers.utils.arrayify(message), - ) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - await contracts.client - .connect(roles.consumer) - .acceptTermsOfService(acceptorAddress, recipientAddress, r, s, v) - - expect( - await contracts.accessControl.hasAccess(recipientAddress, '0x'), - ).to.equal(true) - }) - it('cannot be done by Contract Accounts that if they are not the recipient', async () => { - const acceptorAddress = roles.consumerAddress - const recipientAddress = contracts.coordinator.address - const message = await contracts.accessControl.getMessage( - acceptorAddress, - recipientAddress, - ) - const wallet = new ethers.Wallet(accessControlMockPrivateKey) - const flatSignature = await wallet.signMessage( - ethers.utils.arrayify(message), - ) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - await expect( - contracts.client - .connect(roles.consumer) - .acceptTermsOfService(acceptorAddress, recipientAddress, r, s, v), - ).to.be.revertedWith('InvalidUsage') - }) - }) - - describe('Blocking', () => { - it('can only be done by the Router Owner', async () => { - await expect( - contracts.accessControl - .connect(roles.stranger) - .blockSender(roles.subOwnerAddress), - ).to.be.revertedWith('Only callable by owner') - }) - it('removes the ability to re-accept the terms of service', async () => { - await contracts.accessControl.blockSender(roles.subOwnerAddress) - await expect( - acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ), - ).to.be.revertedWith('RecipientIsBlocked') - }) - it('removes the ability to manage subscriptions', async () => { - await acceptTermsOfService( - contracts.accessControl, - roles.subOwner, - roles.subOwnerAddress, - ) - await contracts.accessControl.blockSender(roles.subOwnerAddress) - await expect( - contracts.router.connect(roles.subOwner).createSubscription(), - ).to.be.revertedWith('SenderMustAcceptTermsOfService') - }) - }) -}) diff --git a/contracts/test/v0.8/functions/v1/utils.ts b/contracts/test/v0.8/functions/v1/utils.ts deleted file mode 100644 index dd3853c2d9d..00000000000 --- a/contracts/test/v0.8/functions/v1/utils.ts +++ /dev/null @@ -1,355 +0,0 @@ -import { ethers } from 'hardhat' -import { BigNumber, ContractFactory, Signer, Contract, providers } from 'ethers' -import { Roles, getUsers } from '../../../test-helpers/setup' -import { EventFragment } from 'ethers/lib/utils' - -export type FunctionsRoles = Roles & { - subOwner: Signer - subOwnerAddress: string - consumer: Signer - consumerAddress: string - stranger: Signer - strangerAddress: string -} - -export type FunctionsFactories = { - functionsRouterFactory: ContractFactory - functionsCoordinatorFactory: ContractFactory - clientTestHelperFactory: ContractFactory - linkTokenFactory: ContractFactory - mockAggregatorV3Factory: ContractFactory - accessControlFactory: ContractFactory -} -export type FunctionsContracts = { - router: Contract - coordinator: Contract - client: Contract - linkToken: Contract - mockLinkEth: Contract - mockLinkUsd: Contract - accessControl: Contract -} - -export const ids = { - routerId: ethers.utils.formatBytes32String(''), - donId: ethers.utils.formatBytes32String('1'), - donId2: ethers.utils.formatBytes32String('2'), - donId3: ethers.utils.formatBytes32String('3'), - donId4: ethers.utils.formatBytes32String('4'), - donId5: ethers.utils.formatBytes32String('5'), -} - -export const anyValue = () => true - -export const stringToHex = (s: string) => { - return ethers.utils.hexlify(ethers.utils.toUtf8Bytes(s)) -} - -export const encodeReport = async ( - requestId: string, - result: string, - err: string, - onchainMetadata: any, - offchainMetadata: string, -) => { - const functionsResponse = await ethers.getContractFactory( - 'src/v0.8/functions/dev/v1_X/FunctionsCoordinator.sol:FunctionsCoordinator', - ) - const onchainMetadataBytes = functionsResponse.interface._abiCoder.encode( - [ - getEventInputs( - Object.values(functionsResponse.interface.events), - 'OracleRequest', - 9, - ), - ], - [[...onchainMetadata]], - ) - const abi = ethers.utils.defaultAbiCoder - return abi.encode( - ['bytes32[]', 'bytes[]', 'bytes[]', 'bytes[]', 'bytes[]'], - [[requestId], [result], [err], [onchainMetadataBytes], [offchainMetadata]], - ) -} - -export type FunctionsRouterConfig = { - maxConsumersPerSubscription: number - adminFee: number - handleOracleFulfillmentSelector: string - maxCallbackGasLimits: number[] - gasForCallExactCheck: number - subscriptionDepositMinimumRequests: number - subscriptionDepositJuels: BigNumber -} -export const functionsRouterConfig: FunctionsRouterConfig = { - maxConsumersPerSubscription: 100, - adminFee: 0, - handleOracleFulfillmentSelector: '0x0ca76175', - maxCallbackGasLimits: [300_000, 500_000, 1_000_000], - gasForCallExactCheck: 5000, - subscriptionDepositMinimumRequests: 10, - subscriptionDepositJuels: BigNumber.from('1000000000000000000'), -} -export type CoordinatorConfig = { - feedStalenessSeconds: number - gasOverheadBeforeCallback: number - gasOverheadAfterCallback: number - requestTimeoutSeconds: number - donFeeCentsUsd: number - maxSupportedRequestDataVersion: number - fulfillmentGasPriceOverEstimationBP: number - fallbackNativePerUnitLink: BigNumber - minimumEstimateGasPriceWei: number - operationFeeCentsUsd: number - fallbackUsdPerUnitLink: number - fallbackUsdPerUnitLinkDecimals: number -} -const fallbackNativePerUnitLink = 5000000000000000 -export const coordinatorConfig: CoordinatorConfig = { - feedStalenessSeconds: 86_400, - gasOverheadBeforeCallback: 44_615, - gasOverheadAfterCallback: 44_615, - requestTimeoutSeconds: 300, - donFeeCentsUsd: 0, - maxSupportedRequestDataVersion: 1, - fulfillmentGasPriceOverEstimationBP: 0, - fallbackNativePerUnitLink: BigNumber.from(fallbackNativePerUnitLink), - minimumEstimateGasPriceWei: 1000000000, - operationFeeCentsUsd: 0, - fallbackUsdPerUnitLink: 1500000000, - fallbackUsdPerUnitLinkDecimals: 8, -} -const linkEthRate = '5021530000000000' -const linkUsdRate = '1500000000' - -export const accessControlMockPublicKey = ethers.utils.getAddress( - '0x32237412cC0321f56422d206e505dB4B3871AF5c', -) -export const accessControlMockPrivateKey = - '2e8c8eaff4159e59711b42424c1555af1b78409e12c6f9c69a6a986d75442b20' -export type AccessControlConfig = { - enabled: boolean - signerPublicKey: string // address -} -export const accessControlConfig: AccessControlConfig = { - enabled: true, - signerPublicKey: accessControlMockPublicKey, -} - -export async function setupRolesAndFactories(): Promise<{ - roles: FunctionsRoles - factories: FunctionsFactories -}> { - const roles = (await getUsers()).roles - const functionsRouterFactory = await ethers.getContractFactory( - 'src/v0.8/functions/dev/v1_X/FunctionsRouter.sol:FunctionsRouter', - roles.defaultAccount, - ) - const functionsCoordinatorFactory = await ethers.getContractFactory( - 'src/v0.8/functions/tests/v1_X/testhelpers/FunctionsCoordinatorTestHelper.sol:FunctionsCoordinatorTestHelper', - roles.defaultAccount, - ) - const accessControlFactory = await ethers.getContractFactory( - 'src/v0.8/functions/dev/v1_X/accessControl/TermsOfServiceAllowList.sol:TermsOfServiceAllowList', - roles.defaultAccount, - ) - const clientTestHelperFactory = await ethers.getContractFactory( - 'src/v0.8/functions/tests/v1_X/testhelpers/FunctionsClientTestHelper.sol:FunctionsClientTestHelper', - roles.consumer, - ) - const linkTokenFactory = await ethers.getContractFactory( - 'src/v0.8/mocks/MockLinkToken.sol:MockLinkToken', - roles.defaultAccount, - ) - const mockAggregatorV3Factory = await ethers.getContractFactory( - 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', - roles.defaultAccount, - ) - return { - roles: { - ...roles, - subOwner: roles.consumer, - subOwnerAddress: await roles.consumer.getAddress(), - consumer: roles.consumer2, - consumerAddress: await roles.consumer2.getAddress(), - stranger: roles.stranger, - strangerAddress: await roles.stranger.getAddress(), - }, - factories: { - functionsRouterFactory, - functionsCoordinatorFactory, - clientTestHelperFactory, - linkTokenFactory, - mockAggregatorV3Factory, - accessControlFactory, - }, - } -} - -export async function acceptTermsOfService( - accessControl: Contract, - acceptor: Signer, - recipientAddress: string, -) { - const acceptorAddress = await acceptor.getAddress() - const message = await accessControl.getMessage( - acceptorAddress, - recipientAddress, - ) - const wallet = new ethers.Wallet(accessControlMockPrivateKey) - const flatSignature = await wallet.signMessage(ethers.utils.arrayify(message)) - const { r, s, v } = ethers.utils.splitSignature(flatSignature) - return accessControl - .connect(acceptor) - .acceptTermsOfService(acceptorAddress, recipientAddress, r, s, v) -} - -export async function createSubscription( - owner: Signer, - consumers: string[], - router: Contract, - accessControl: Contract, - linkToken?: Contract, -): Promise { - const ownerAddress = await owner.getAddress() - await acceptTermsOfService(accessControl, owner, ownerAddress) - const tx = await router.connect(owner).createSubscription() - const receipt = await tx.wait() - const subId = receipt.events[0].args['subscriptionId'].toNumber() - for (let i = 0; i < consumers.length; i++) { - await router.connect(owner).addConsumer(subId, consumers[i]) - } - if (linkToken) { - await linkToken - .connect(owner) - .transferAndCall( - router.address, - BigNumber.from('1000000000000000000'), - ethers.utils.defaultAbiCoder.encode(['uint64'], [subId]), - ) - } - return subId -} - -export function getSetupFactory(): () => { - contracts: FunctionsContracts - factories: FunctionsFactories - roles: FunctionsRoles -} { - let contracts: FunctionsContracts - let factories: FunctionsFactories - let roles: FunctionsRoles - - before(async () => { - const { roles: r, factories: f } = await setupRolesAndFactories() - factories = f - roles = r - }) - - beforeEach(async () => { - // Deploy - const linkToken = await factories.linkTokenFactory - .connect(roles.defaultAccount) - .deploy() - - const mockLinkEth = await factories.mockAggregatorV3Factory.deploy( - 0, - BigNumber.from(linkEthRate), - ) - - const mockLinkUsd = await factories.mockAggregatorV3Factory.deploy( - 0, - BigNumber.from(linkUsdRate), - ) - - const router = await factories.functionsRouterFactory - .connect(roles.defaultAccount) - .deploy(linkToken.address, functionsRouterConfig) - - const coordinator = await factories.functionsCoordinatorFactory - .connect(roles.defaultAccount) - .deploy( - router.address, - coordinatorConfig, - mockLinkEth.address, - mockLinkUsd.address, - ) - - const initialAllowedSenders: string[] = [] - const initialBlockedSenders: string[] = [] - const accessControl = await factories.accessControlFactory - .connect(roles.defaultAccount) - .deploy(accessControlConfig, initialAllowedSenders, initialBlockedSenders) - - const client = await factories.clientTestHelperFactory - .connect(roles.consumer) - .deploy(router.address) - - // Setup accounts - await linkToken.transfer( - roles.subOwnerAddress, - BigNumber.from('1000000000000000000'), // 1 LINK - ) - await linkToken.transfer( - roles.strangerAddress, - BigNumber.from('1000000000000000000'), // 1 LINK - ) - - const allowListId = await router.getAllowListId() - await router.proposeContractsUpdate( - [ids.donId, allowListId], - [coordinator.address, accessControl.address], - ) - await router.updateContracts() - - contracts = { - client, - coordinator, - router, - linkToken, - mockLinkEth, - mockLinkUsd, - accessControl, - } - }) - - return () => { - return { contracts, factories, roles } - } -} - -export function getEventArg(events: any, eventName: string, argIndex: number) { - if (Array.isArray(events)) { - const event = events.find((e: any) => e.event === eventName) - if (event && Array.isArray(event.args) && event.args.length > 0) { - return event.args[argIndex] - } - } - return undefined -} - -export function getEventInputs( - events: EventFragment[], - eventName: string, - argIndex: number, -) { - if (Array.isArray(events)) { - const event = events.find((e) => e.name.includes(eventName)) - if (event && Array.isArray(event.inputs) && event.inputs.length > 0) { - return event.inputs[argIndex] - } - } - throw 'Not found' -} - -export async function parseOracleRequestEventArgs( - tx: providers.TransactionResponse, -) { - const receipt = await tx.wait() - const data = receipt.logs?.[1].data - // NOTE: indexed args are on topics, not data - return ethers.utils.defaultAbiCoder.decode( - ['address', 'uint64', 'address', 'bytes', 'uint16'], - data ?? '', - ) -} diff --git a/contracts/test/v0.8/operatorforwarder/ConfirmedOwner.test.ts b/contracts/test/v0.8/operatorforwarder/ConfirmedOwner.test.ts index 3bd347320c5..67caa28bc38 100644 --- a/contracts/test/v0.8/operatorforwarder/ConfirmedOwner.test.ts +++ b/contracts/test/v0.8/operatorforwarder/ConfirmedOwner.test.ts @@ -2,7 +2,7 @@ import { ethers } from 'hardhat' import { publicAbi } from '../../test-helpers/helpers' import { assert, expect } from 'chai' import { Contract, ContractFactory, Signer } from 'ethers' -import { Personas, getUsers } from '../../test-helpers/setup' +import { getUsers, Personas } from '../../test-helpers/setup' import { evmRevert } from '../../test-helpers/matchers' let confirmedOwnerTestHelperFactory: ContractFactory @@ -13,6 +13,7 @@ let owner: Signer let nonOwner: Signer let newOwner: Signer +// TODO rewrite in Foundry before(async () => { const users = await getUsers() personas = users.personas @@ -21,7 +22,7 @@ before(async () => { newOwner = personas.Ned confirmedOwnerTestHelperFactory = await ethers.getContractFactory( - 'src/v0.7/tests/ConfirmedOwnerTestHelper.sol:ConfirmedOwnerTestHelper', + 'src/v0.8/shared/test/testhelpers/ConfirmedOwnerTestHelper.sol:ConfirmedOwnerTestHelper', owner, ) confirmedOwnerFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/operatorforwarder/Operator.test.ts b/contracts/test/v0.8/operatorforwarder/Operator.test.ts index a4a0ed8a1c5..d46bcccace0 100644 --- a/contracts/test/v0.8/operatorforwarder/Operator.test.ts +++ b/contracts/test/v0.8/operatorforwarder/Operator.test.ts @@ -31,7 +31,6 @@ import { RunRequest, } from '../../test-helpers/oracle' -let v7ConsumerFactory: ContractFactory let basicConsumerFactory: ContractFactory let multiWordConsumerFactory: ContractFactory let gasGuzzlingConsumerFactory: ContractFactory @@ -50,17 +49,14 @@ before(async () => { const users = await getUsers() roles = users.roles - v7ConsumerFactory = await ethers.getContractFactory( - 'src/v0.7/tests/Consumer.sol:Consumer', - ) basicConsumerFactory = await ethers.getContractFactory( - 'src/v0.6/tests/BasicConsumer.sol:BasicConsumer', + 'src/v0.8/operatorforwarder/dev/tests/testhelpers/BasicConsumer.sol:BasicConsumer', ) multiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.7/tests/MultiWordConsumer.sol:MultiWordConsumer', + 'src/v0.8/operatorforwarder/dev/tests/testhelpers/MultiWordConsumer.sol:MultiWordConsumer', ) gasGuzzlingConsumerFactory = await ethers.getContractFactory( - 'src/v0.6/tests/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', + 'src/v0.8/operatorforwarder/dev/tests/testhelpers/GasGuzzlingConsumer.sol:GasGuzzlingConsumer', ) getterSetterFactory = await ethers.getContractFactory( 'src/v0.8/operatorforwarder/dev/tests/testhelpers/GetterSetter.sol:GetterSetter', @@ -72,7 +68,7 @@ before(async () => { 'src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousConsumer.sol:MaliciousConsumer', ) maliciousMultiWordConsumerFactory = await ethers.getContractFactory( - 'src/v0.6/tests/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', + 'src/v0.8/operatorforwarder/dev/tests/testhelpers/MaliciousMultiWordConsumer.sol:MaliciousMultiWordConsumer', ) operatorFactory = await ethers.getContractFactory( 'src/v0.8/operatorforwarder/dev/Operator.sol:Operator', @@ -1079,15 +1075,15 @@ describe('Operator', () => { }) describe('when fulfilled with the wrong function', () => { - let v7Consumer + let basicConsumer beforeEach(async () => { - v7Consumer = await v7ConsumerFactory + basicConsumer = await basicConsumerFactory .connect(roles.defaultAccount) .deploy(link.address, operator.address, specId) const paymentAmount = toWei('1') - await link.transfer(v7Consumer.address, paymentAmount) + await link.transfer(basicConsumer.address, paymentAmount) const currency = 'USD' - const tx = await v7Consumer.requestEthereumPrice( + const tx = await basicConsumer.requestEthereumPrice( currency, paymentAmount, ) @@ -1204,6 +1200,7 @@ describe('Operator', () => { ) }) + // TODO BCF-3117 // it('cannot call functions on the LINK token through callbacks', async () => { // await evmRevert( // maliciousRequester.request( @@ -1746,6 +1743,7 @@ describe('Operator', () => { ) }) + // TODO BCF-3117 // it('cannot call functions on the LINK token through callbacks', async () => { // await evmRevert( // maliciousRequester.request( @@ -2302,6 +2300,7 @@ describe('Operator', () => { ) }) + // TODO BCF-3117 // it('cannot call functions on the LINK token through callbacks', async () => { // await evmRevert( // maliciousRequester.request( @@ -2835,6 +2834,7 @@ describe('Operator', () => { ) }) + // TODO BCF-3117 // it('cannot call functions on the LINK token through callbacks', async () => { // await evmRevert( // maliciousRequester.request( diff --git a/contracts/test/v0.8/dev/BatchBlockhashStore.test.ts b/contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts similarity index 99% rename from contracts/test/v0.8/dev/BatchBlockhashStore.test.ts rename to contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts index 6821184fde1..ebdc17037ce 100644 --- a/contracts/test/v0.8/dev/BatchBlockhashStore.test.ts +++ b/contracts/test/v0.8/vrf/BatchBlockhashStore.test.ts @@ -17,7 +17,7 @@ describe('BatchBlockhashStore', () => { owner = accounts[0] const bhFactory = await ethers.getContractFactory( - 'src/v0.6/BlockhashStore.sol:BlockhashStore', + 'src/v0.8/vrf/dev/BlockhashStore.sol:BlockhashStore', accounts[0], ) diff --git a/contracts/test/v0.8/dev/VRFCoordinatorV2.test.ts b/contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts similarity index 99% rename from contracts/test/v0.8/dev/VRFCoordinatorV2.test.ts rename to contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts index 019581a256f..2df64986e6e 100644 --- a/contracts/test/v0.8/dev/VRFCoordinatorV2.test.ts +++ b/contracts/test/v0.8/vrf/VRFCoordinatorV2.test.ts @@ -1,5 +1,5 @@ import { ethers } from 'hardhat' -import { Signer, Contract, BigNumber } from 'ethers' +import { BigNumber, Contract, Signer } from 'ethers' import { assert, expect } from 'chai' import { publicAbi } from '../../test-helpers/helpers' import { randomAddressString } from 'hardhat/internal/hardhat-network/provider/utils/random' @@ -42,12 +42,12 @@ describe('VRFCoordinatorV2', () => { ) linkToken = await ltFactory.deploy() const bhFactory = await ethers.getContractFactory( - 'src/v0.6/BlockhashStore.sol:BlockhashStore', + 'src/v0.8/vrf/dev/BlockhashStore.sol:BlockhashStore', accounts[0], ) blockHashStore = await bhFactory.deploy() const mockAggregatorV3Factory = await ethers.getContractFactory( - 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator', + 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', accounts[0], ) mockLinkEth = await mockAggregatorV3Factory.deploy(0, linkEth) @@ -899,7 +899,7 @@ describe('VRFCoordinatorV2', () => { it('non-positive link wei price should revert', async function () { const mockAggregatorV3Factory = await ethers.getContractFactory( - 'src/v0.7/tests/MockV3Aggregator.sol:MockV3Aggregator', + 'src/v0.8/tests/MockV3Aggregator.sol:MockV3Aggregator', owner, ) const vrfCoordinatorV2TestHelperFactory = await ethers.getContractFactory( diff --git a/contracts/test/v0.8/dev/VRFCoordinatorV2Mock.test.ts b/contracts/test/v0.8/vrf/VRFCoordinatorV2Mock.test.ts similarity index 100% rename from contracts/test/v0.8/dev/VRFCoordinatorV2Mock.test.ts rename to contracts/test/v0.8/vrf/VRFCoordinatorV2Mock.test.ts diff --git a/contracts/test/v0.8/VRFSubscriptionBalanceMonitor.test.ts b/contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts similarity index 99% rename from contracts/test/v0.8/VRFSubscriptionBalanceMonitor.test.ts rename to contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts index 01af5b826a3..15d35f638f9 100644 --- a/contracts/test/v0.8/VRFSubscriptionBalanceMonitor.test.ts +++ b/contracts/test/v0.8/vrf/VRFSubscriptionBalanceMonitor.test.ts @@ -4,8 +4,8 @@ import type { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers' import { LinkToken, VRFSubscriptionBalanceMonitorExposed, -} from '../../typechain' -import * as h from '../test-helpers/helpers' +} from '../../../typechain' +import * as h from '../../test-helpers/helpers' import { BigNumber, Contract } from 'ethers' const OWNABLE_ERR = 'Only callable by owner' diff --git a/contracts/test/v0.8/dev/VRFV2Wrapper.test.ts b/contracts/test/v0.8/vrf/VRFV2Wrapper.test.ts similarity index 100% rename from contracts/test/v0.8/dev/VRFV2Wrapper.test.ts rename to contracts/test/v0.8/vrf/VRFV2Wrapper.test.ts diff --git a/core/chains/evm/client/chain_client.go b/core/chains/evm/client/chain_client.go index 1eb2347c474..52bc1263c75 100644 --- a/core/chains/evm/client/chain_client.go +++ b/core/chains/evm/client/chain_client.go @@ -38,7 +38,8 @@ type chainClient struct { RPCClient, rpc.BatchElem, ] - logger logger.SugaredLogger + logger logger.SugaredLogger + chainType config.ChainType } func NewChainClient( @@ -269,3 +270,12 @@ func (c *chainClient) TransactionReceipt(ctx context.Context, txHash common.Hash func (c *chainClient) LatestFinalizedBlock(ctx context.Context) (*evmtypes.Head, error) { return c.multiNode.LatestFinalizedBlock(ctx) } + +func (c *chainClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError { + msg := ethereum.CallMsg{ + From: from, + To: &to, + Data: data, + } + return SimulateTransaction(ctx, c, c.logger, c.chainType, msg) +} diff --git a/core/chains/evm/client/client.go b/core/chains/evm/client/client.go index ee33db97fd6..2758c9cf0a4 100644 --- a/core/chains/evm/client/client.go +++ b/core/chains/evm/client/client.go @@ -95,6 +95,9 @@ type Client interface { PendingCallContract(ctx context.Context, msg ethereum.CallMsg) ([]byte, error) IsL2() bool + + // Simulate the transaction prior to sending to catch zk out-of-counters errors ahead of time + CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError } func ContextWithDefaultTimeout() (ctx context.Context, cancel context.CancelFunc) { @@ -371,3 +374,7 @@ func (client *client) IsL2() bool { func (client *client) LatestFinalizedBlock(_ context.Context) (*evmtypes.Head, error) { return nil, pkgerrors.New("not implemented. client was deprecated. New methods are added only to satisfy type constraints while we are migrating to new alternatives") } + +func (client *client) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError { + return NewSendError(pkgerrors.New("not implemented. client was deprecated. New methods are added only to satisfy type constraints while we are migrating to new alternatives")) +} diff --git a/core/chains/evm/client/config_builder.go b/core/chains/evm/client/config_builder.go index c004bc4e9c6..d78a981b881 100644 --- a/core/chains/evm/client/config_builder.go +++ b/core/chains/evm/client/config_builder.go @@ -8,12 +8,13 @@ import ( "go.uber.org/multierr" commonconfig "github.com/smartcontractkit/chainlink-common/pkg/config" - "github.com/smartcontractkit/chainlink/v2/common/config" + + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" ) -type nodeConfig struct { +type NodeConfig struct { Name *string WSURL *string HTTPURL *string @@ -28,15 +29,19 @@ func NewClientConfigs( selectionMode *string, leaseDuration time.Duration, chainType string, - nodeCfgs []nodeConfig, + nodeCfgs []NodeConfig, pollFailureThreshold *uint32, pollInterval time.Duration, syncThreshold *uint32, nodeIsSyncingEnabled *bool, -) (evmconfig.NodePool, []*toml.Node, config.ChainType, error) { + noNewHeadsThreshold time.Duration, + finalityDepth *uint32, + finalityTagEnabled *bool, + +) (commonclient.ChainConfig, evmconfig.NodePool, []*toml.Node, error) { nodes, err := parseNodeConfigs(nodeCfgs) if err != nil { - return nil, nil, "", err + return nil, nil, nil, err } nodePool := toml.NodePool{ SelectionMode: selectionMode, @@ -47,10 +52,20 @@ func NewClientConfigs( NodeIsSyncingEnabled: nodeIsSyncingEnabled, } nodePoolCfg := &evmconfig.NodePoolConfig{C: nodePool} - return nodePoolCfg, nodes, config.ChainType(chainType), nil + chainConfig := &evmconfig.EVMConfig{ + C: &toml.EVMConfig{ + Chain: toml.Chain{ + ChainType: &chainType, + FinalityDepth: finalityDepth, + FinalityTagEnabled: finalityTagEnabled, + NoNewHeadsThreshold: commonconfig.MustNewDuration(noNewHeadsThreshold), + }, + }, + } + return chainConfig, nodePoolCfg, nodes, nil } -func parseNodeConfigs(nodeCfgs []nodeConfig) ([]*toml.Node, error) { +func parseNodeConfigs(nodeCfgs []NodeConfig) ([]*toml.Node, error) { nodes := make([]*toml.Node, len(nodeCfgs)) for i, nodeCfg := range nodeCfgs { if nodeCfg.WSURL == nil || nodeCfg.HTTPURL == nil { diff --git a/core/chains/evm/client/config_builder_test.go b/core/chains/evm/client/config_builder_test.go index cc00029d270..43a33859615 100644 --- a/core/chains/evm/client/config_builder_test.go +++ b/core/chains/evm/client/config_builder_test.go @@ -1,12 +1,14 @@ package client_test import ( + "math/big" "testing" "time" "github.com/stretchr/testify/require" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/logger" ) func TestClientConfigBuilder(t *testing.T) { @@ -19,14 +21,18 @@ func TestClientConfigBuilder(t *testing.T) { syncThreshold := ptr(uint32(5)) nodeIsSyncingEnabled := ptr(false) chainTypeStr := "" - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo"), WSURL: ptr("ws://foo.test"), HTTPURL: ptr("http://foo.test"), }, } - nodePool, nodes, chainType, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled) + finalityDepth := ptr(uint32(10)) + finalityTagEnabled := ptr(true) + noNewHeadsThreshold := time.Second + chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, + pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, finalityTagEnabled) require.NoError(t, err) // Validate node pool configs @@ -42,15 +48,21 @@ func TestClientConfigBuilder(t *testing.T) { require.Equal(t, *nodeConfigs[0].WSURL, (*nodes[0].WSURL).String()) require.Equal(t, *nodeConfigs[0].HTTPURL, (*nodes[0].HTTPURL).String()) - // Validate chain type - require.Equal(t, chainTypeStr, string(chainType)) + // Validate chain config + require.Equal(t, chainTypeStr, string(chainCfg.ChainType())) + require.Equal(t, noNewHeadsThreshold, chainCfg.NodeNoNewHeadsThreshold()) + require.Equal(t, *finalityDepth, chainCfg.FinalityDepth()) + require.Equal(t, *finalityTagEnabled, chainCfg.FinalityTagEnabled()) + + // let combiler tell us, when we do not have sufficient data to create evm client + _ = client.NewEvmClient(nodePool, chainCfg, logger.TestLogger(t), big.NewInt(10), nodes) } func TestNodeConfigs(t *testing.T) { t.Parallel() t.Run("parsing unique node configs succeeds", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -68,7 +80,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing missing ws url fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), HTTPURL: ptr("http://foo1.test"), @@ -79,7 +91,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing missing http url fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -90,7 +102,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing invalid ws url fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("http://foo1.test"), @@ -102,7 +114,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing duplicate http url fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -114,7 +126,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing duplicate node names fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -131,7 +143,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing duplicate node ws urls fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -148,7 +160,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing duplicate node http urls fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), @@ -165,7 +177,7 @@ func TestNodeConfigs(t *testing.T) { }) t.Run("parsing order too large fails", func(t *testing.T) { - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo1"), WSURL: ptr("ws://foo1.test"), diff --git a/core/chains/evm/client/errors.go b/core/chains/evm/client/errors.go index 8095c122508..37572bc8643 100644 --- a/core/chains/evm/client/errors.go +++ b/core/chains/evm/client/errors.go @@ -63,6 +63,7 @@ const ( TransactionAlreadyMined Fatal ServiceUnavailable + OutOfCounters ) type ClientErrors = map[int]*regexp.Regexp @@ -224,10 +225,15 @@ var zkSync = ClientErrors{ // can't start a transaction from a non-account - trying to send from an invalid address, e.g. estimating a contract -> contract tx // max fee per gas higher than 2^64-1 - uint64 overflow // oversized data - data too large - Fatal: regexp.MustCompile(`(?:: |^)(?:exceeds block gas limit|intrinsic gas too low|Not enough gas for transaction validation|Failed to pay the fee to the operator|Error function_selector = 0x, data = 0x|invalid sender. can't start a transaction from a non-account|max(?: priority)? fee per (?:gas|pubdata byte) higher than 2\^64-1|oversized data. max: \d+; actual: \d+)$`), + Fatal: regexp.MustCompile(`(?:: |^)(?:exceeds block gas limit|intrinsic gas too low|Not enough gas for transaction validation|Failed to pay the fee to the operator|Error function_selector = 0x, data = 0x|invalid sender. can't start a transaction from a non-account|max(?: priority)? fee per (?:gas|pubdata byte) higher than 2\^64-1|oversized data. max: \d+; actual: \d+)$`), + TransactionAlreadyInMempool: regexp.MustCompile(`known transaction. transaction with hash .* is already in the system`), } -var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync} +var zkEvm = ClientErrors{ + OutOfCounters: regexp.MustCompile(`(?:: |^)not enough .* counters to continue the execution$`), +} + +var clients = []ClientErrors{parity, geth, arbitrum, metis, substrate, avalanche, nethermind, harmony, besu, erigon, klaytn, celo, zkSync, zkEvm} func (s *SendError) is(errorType int) bool { if s == nil || s.err == nil { @@ -309,6 +315,11 @@ func (s *SendError) IsServiceUnavailable() bool { return s.is(ServiceUnavailable) } +// IsOutOfCounters is a zk chain specific error returned if the transaction is too complex to prove on zk circuits +func (s *SendError) IsOutOfCounters() bool { + return s.is(OutOfCounters) +} + // IsTimeout indicates if the error was caused by an exceeded context deadline func (s *SendError) IsTimeout() bool { if s == nil { diff --git a/core/chains/evm/client/errors_test.go b/core/chains/evm/client/errors_test.go index a59d3fbf719..5d1fa135725 100644 --- a/core/chains/evm/client/errors_test.go +++ b/core/chains/evm/client/errors_test.go @@ -127,6 +127,9 @@ func Test_Eth_Errors(t *testing.T) { {"call failed: AlreadyKnown", true, "Nethermind"}, {"call failed: OwnNonceAlreadyUsed", true, "Nethermind"}, {"known transaction", true, "Klaytn"}, + {"known transaction. transaction with hash 0x6013…3053 is already in the system", true, "zkSync"}, + // This seems to be an erroneous message from the zkSync client, we'll have to match it anyway + {"ErrorObject { code: ServerError(3), message: \\\"known transaction. transaction with hash 0xf016…ad63 is already in the system\\\", data: Some(RawValue(\\\"0x\\\")) }", true, "zkSync"}, } for _, test := range tests { err = evmclient.NewSendErrorS(test.message) diff --git a/core/chains/evm/client/evm_client.go b/core/chains/evm/client/evm_client.go index cd7d4a74b80..f60605bc88e 100644 --- a/core/chains/evm/client/evm_client.go +++ b/core/chains/evm/client/evm_client.go @@ -3,17 +3,16 @@ package client import ( "math/big" "net/url" - "time" "github.com/smartcontractkit/chainlink-common/pkg/logger" + commonclient "github.com/smartcontractkit/chainlink/v2/common/client" - "github.com/smartcontractkit/chainlink/v2/common/config" evmconfig "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" evmtypes "github.com/smartcontractkit/chainlink/v2/core/chains/evm/types" ) -func NewEvmClient(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lggr logger.Logger, chainID *big.Int, chainType config.ChainType, nodes []*toml.Node) Client { +func NewEvmClient(cfg evmconfig.NodePool, chainCfg commonclient.ChainConfig, lggr logger.Logger, chainID *big.Int, nodes []*toml.Node) Client { var empty url.URL var primaries []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient] var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient] @@ -27,11 +26,12 @@ func NewEvmClient(cfg evmconfig.NodePool, noNewHeadsThreshold time.Duration, lgg } else { rpc := NewRPCClient(lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), *node.Name, int32(i), chainID, commonclient.Primary) - primaryNode := commonclient.NewNode(cfg, noNewHeadsThreshold, + primaryNode := commonclient.NewNode(cfg, chainCfg, lggr, (url.URL)(*node.WSURL), (*url.URL)(node.HTTPURL), *node.Name, int32(i), chainID, *node.Order, rpc, "EVM") primaries = append(primaries, primaryNode) } } - return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), noNewHeadsThreshold, primaries, sendonlys, chainID, chainType) + return NewChainClient(lggr, cfg.SelectionMode(), cfg.LeaseDuration(), chainCfg.NodeNoNewHeadsThreshold(), + primaries, sendonlys, chainID, chainCfg.ChainType()) } diff --git a/core/chains/evm/client/evm_client_test.go b/core/chains/evm/client/evm_client_test.go index 2764a2b3611..1542e41265b 100644 --- a/core/chains/evm/client/evm_client_test.go +++ b/core/chains/evm/client/evm_client_test.go @@ -22,16 +22,19 @@ func TestNewEvmClient(t *testing.T) { syncThreshold := ptr(uint32(5)) nodeIsSyncingEnabled := ptr(false) chainTypeStr := "" - nodeConfigs := []client.TestNodeConfig{ + nodeConfigs := []client.NodeConfig{ { Name: ptr("foo"), WSURL: ptr("ws://foo.test"), HTTPURL: ptr("http://foo.test"), }, } - nodePool, nodes, chainType, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled) + finalityDepth := ptr(uint32(10)) + finalityTagEnabled := ptr(true) + chainCfg, nodePool, nodes, err := client.NewClientConfigs(selectionMode, leaseDuration, chainTypeStr, nodeConfigs, + pollFailureThreshold, pollInterval, syncThreshold, nodeIsSyncingEnabled, noNewHeadsThreshold, finalityDepth, finalityTagEnabled) require.NoError(t, err) - client := client.NewEvmClient(nodePool, noNewHeadsThreshold, logger.TestLogger(t), testutils.FixtureChainID, chainType, nodes) + client := client.NewEvmClient(nodePool, chainCfg, logger.TestLogger(t), testutils.FixtureChainID, nodes) require.NotNil(t, client) } diff --git a/core/chains/evm/client/helpers_test.go b/core/chains/evm/client/helpers_test.go index 1decf3ed89d..2a360219046 100644 --- a/core/chains/evm/client/helpers_test.go +++ b/core/chains/evm/client/helpers_test.go @@ -12,6 +12,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/logger" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" + clientMocks "github.com/smartcontractkit/chainlink/v2/common/client/mocks" commonconfig "github.com/smartcontractkit/chainlink/v2/common/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/config/toml" @@ -19,12 +20,13 @@ import ( ) type TestNodePoolConfig struct { - NodePollFailureThreshold uint32 - NodePollInterval time.Duration - NodeSelectionMode string - NodeSyncThreshold uint32 - NodeLeaseDuration time.Duration - NodeIsSyncingEnabledVal bool + NodePollFailureThreshold uint32 + NodePollInterval time.Duration + NodeSelectionMode string + NodeSyncThreshold uint32 + NodeLeaseDuration time.Duration + NodeIsSyncingEnabledVal bool + NodeFinalizedBlockPollInterval time.Duration } func (tc TestNodePoolConfig) PollFailureThreshold() uint32 { return tc.NodePollFailureThreshold } @@ -39,6 +41,10 @@ func (tc TestNodePoolConfig) NodeIsSyncingEnabled() bool { return tc.NodeIsSyncingEnabledVal } +func (tc TestNodePoolConfig) FinalizedBlockPollInterval() time.Duration { + return tc.NodeFinalizedBlockPollInterval +} + func NewClientWithTestNode(t *testing.T, nodePoolCfg config.NodePool, noNewHeadsThreshold time.Duration, rpcUrl string, rpcHTTPURL *url.URL, sendonlyRPCURLs []url.URL, id int32, chainID *big.Int) (*client, error) { parsed, err := url.ParseRequestURI(rpcUrl) if err != nil { @@ -97,7 +103,7 @@ func NewChainClientWithTestNode( rpc := NewRPCClient(lggr, *parsed, rpcHTTPURL, "eth-primary-rpc-0", id, chainID, commonclient.Primary) n := commonclient.NewNode[*big.Int, *evmtypes.Head, RPCClient]( - nodeCfg, noNewHeadsThreshold, lggr, *parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM") + nodeCfg, clientMocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, *parsed, rpcHTTPURL, "eth-primary-node-0", id, chainID, 1, rpc, "EVM") primaries := []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient]{n} var sendonlys []commonclient.SendOnlyNode[*big.Int, RPCClient] @@ -153,7 +159,7 @@ func NewChainClientWithMockedRpc( parsed, _ := url.ParseRequestURI("ws://test") n := commonclient.NewNode[*big.Int, *evmtypes.Head, RPCClient]( - cfg, noNewHeadsThreshold, lggr, *parsed, nil, "eth-primary-node-0", 1, chainID, 1, rpc, "EVM") + cfg, clientMocks.ChainConfig{NoNewHeadsThresholdVal: noNewHeadsThreshold}, lggr, *parsed, nil, "eth-primary-node-0", 1, chainID, 1, rpc, "EVM") primaries := []commonclient.Node[*big.Int, *evmtypes.Head, RPCClient]{n} c := NewChainClient(lggr, selectionMode, leaseDuration, noNewHeadsThreshold, primaries, nil, chainID, chainType) t.Cleanup(c.Close) @@ -187,8 +193,6 @@ func (mes *mockSubscription) Unsubscribe() { close(mes.Errors) } -type TestNodeConfig = nodeConfig - -func ParseTestNodeConfigs(nodes []TestNodeConfig) ([]*toml.Node, error) { +func ParseTestNodeConfigs(nodes []NodeConfig) ([]*toml.Node, error) { return parseNodeConfigs(nodes) } diff --git a/core/chains/evm/client/mocks/client.go b/core/chains/evm/client/mocks/client.go index e6c9da1cbe9..b3cdac3a6b6 100644 --- a/core/chains/evm/client/mocks/client.go +++ b/core/chains/evm/client/mocks/client.go @@ -7,6 +7,8 @@ import ( assets "github.com/smartcontractkit/chainlink-common/pkg/assets" + client "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + common "github.com/ethereum/go-ethereum/common" commonclient "github.com/smartcontractkit/chainlink/v2/common/client" @@ -236,6 +238,26 @@ func (_m *Client) ChainID() (*big.Int, error) { return r0, r1 } +// CheckTxValidity provides a mock function with given fields: ctx, from, to, data +func (_m *Client) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *client.SendError { + ret := _m.Called(ctx, from, to, data) + + if len(ret) == 0 { + panic("no return value specified for CheckTxValidity") + } + + var r0 *client.SendError + if rf, ok := ret.Get(0).(func(context.Context, common.Address, common.Address, []byte) *client.SendError); ok { + r0 = rf(ctx, from, to, data) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*client.SendError) + } + } + + return r0 +} + // Close provides a mock function with given fields: func (_m *Client) Close() { _m.Called() diff --git a/core/chains/evm/client/null_client.go b/core/chains/evm/client/null_client.go index e4bd7d1dd9a..3129bcff9b0 100644 --- a/core/chains/evm/client/null_client.go +++ b/core/chains/evm/client/null_client.go @@ -231,3 +231,7 @@ func (nc *NullClient) IsL2() bool { func (nc *NullClient) LatestFinalizedBlock(_ context.Context) (*evmtypes.Head, error) { return nil, nil } + +func (nc *NullClient) CheckTxValidity(_ context.Context, _ common.Address, _ common.Address, _ []byte) *SendError { + return nil +} diff --git a/core/chains/evm/client/simulated_backend_client.go b/core/chains/evm/client/simulated_backend_client.go index 5750887126a..9fe2ff88ba7 100644 --- a/core/chains/evm/client/simulated_backend_client.go +++ b/core/chains/evm/client/simulated_backend_client.go @@ -774,6 +774,10 @@ func (c *SimulatedBackendClient) ethGetLogs(ctx context.Context, result interfac } } +func (c *SimulatedBackendClient) CheckTxValidity(ctx context.Context, from common.Address, to common.Address, data []byte) *SendError { + return nil +} + func toCallMsg(params map[string]interface{}) ethereum.CallMsg { var callMsg ethereum.CallMsg toAddr, err := interfaceToAddress(params["to"]) diff --git a/core/chains/evm/client/tx_simulator.go b/core/chains/evm/client/tx_simulator.go new file mode 100644 index 00000000000..65e108bd227 --- /dev/null +++ b/core/chains/evm/client/tx_simulator.go @@ -0,0 +1,55 @@ +package client + +import ( + "context" + + "github.com/ethereum/go-ethereum" + "github.com/ethereum/go-ethereum/common/hexutil" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + "github.com/smartcontractkit/chainlink/v2/common/config" +) + +type simulatorClient interface { + CallContext(ctx context.Context, result interface{}, method string, args ...interface{}) error +} + +// ZK chains can return an out-of-counters error +// This method allows a caller to determine if a tx would fail due to OOC error by simulating the transaction +// Used as an entry point in case custom simulation is required across different chains +func SimulateTransaction(ctx context.Context, client simulatorClient, lggr logger.SugaredLogger, chainType config.ChainType, msg ethereum.CallMsg) *SendError { + err := simulateTransactionDefault(ctx, client, msg) + return NewSendError(err) +} + +// eth_estimateGas returns out-of-counters (OOC) error if the transaction would result in an overflow +func simulateTransactionDefault(ctx context.Context, client simulatorClient, msg ethereum.CallMsg) error { + var result hexutil.Big + return client.CallContext(ctx, &result, "eth_estimateGas", toCallArg(msg), "pending") +} + +func toCallArg(msg ethereum.CallMsg) interface{} { + arg := map[string]interface{}{ + "from": msg.From, + "to": msg.To, + } + if len(msg.Data) > 0 { + arg["input"] = hexutil.Bytes(msg.Data) + } + if msg.Value != nil { + arg["value"] = (*hexutil.Big)(msg.Value) + } + if msg.Gas != 0 { + arg["gas"] = hexutil.Uint64(msg.Gas) + } + if msg.GasPrice != nil { + arg["gasPrice"] = (*hexutil.Big)(msg.GasPrice) + } + if msg.GasFeeCap != nil { + arg["maxFeePerGas"] = (*hexutil.Big)(msg.GasFeeCap) + } + if msg.GasTipCap != nil { + arg["maxPriorityFeePerGas"] = (*hexutil.Big)(msg.GasTipCap) + } + return arg +} diff --git a/core/chains/evm/client/tx_simulator_test.go b/core/chains/evm/client/tx_simulator_test.go new file mode 100644 index 00000000000..4e270d401bf --- /dev/null +++ b/core/chains/evm/client/tx_simulator_test.go @@ -0,0 +1,113 @@ +package client_test + +import ( + "testing" + + "github.com/ethereum/go-ethereum" + "github.com/stretchr/testify/require" + "github.com/tidwall/gjson" + + "github.com/smartcontractkit/chainlink-common/pkg/logger" + + "github.com/smartcontractkit/chainlink/v2/core/chains/evm/client" + "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +func TestSimulateTx_Default(t *testing.T) { + t.Parallel() + + fromAddress := testutils.NewAddress() + toAddress := testutils.NewAddress() + ctx := testutils.Context(t) + + t.Run("returns without error if simulation passes", func(t *testing.T) { + wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + switch method { + case "eth_subscribe": + resp.Result = `"0x00"` + resp.Notify = headResult + return + case "eth_unsubscribe": + resp.Result = "true" + return + case "eth_estimateGas": + resp.Result = `"0x100"` + } + return + }).WSURL().String() + + ethClient := mustNewChainClient(t, wsURL) + err := ethClient.Dial(ctx) + require.NoError(t, err) + + msg := ethereum.CallMsg{ + From: fromAddress, + To: &toAddress, + Data: []byte("0x00"), + } + sendErr := client.SimulateTransaction(ctx, ethClient, logger.TestSugared(t), "", msg) + require.Empty(t, sendErr) + }) + + t.Run("returns error if simulation returns zk out-of-counters error", func(t *testing.T) { + wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + switch method { + case "eth_subscribe": + resp.Result = `"0x00"` + resp.Notify = headResult + return + case "eth_unsubscribe": + resp.Result = "true" + return + case "eth_estimateGas": + resp.Error.Code = -32000 + resp.Result = `"0x100"` + resp.Error.Message = "not enough keccak counters to continue the execution" + } + return + }).WSURL().String() + + ethClient := mustNewChainClient(t, wsURL) + err := ethClient.Dial(ctx) + require.NoError(t, err) + + msg := ethereum.CallMsg{ + From: fromAddress, + To: &toAddress, + Data: []byte("0x00"), + } + sendErr := client.SimulateTransaction(ctx, ethClient, logger.TestSugared(t), "", msg) + require.Equal(t, true, sendErr.IsOutOfCounters()) + }) + + t.Run("returns without error if simulation returns non-OOC error", func(t *testing.T) { + wsURL := testutils.NewWSServer(t, &cltest.FixtureChainID, func(method string, params gjson.Result) (resp testutils.JSONRPCResponse) { + switch method { + case "eth_subscribe": + resp.Result = `"0x00"` + resp.Notify = headResult + return + case "eth_unsubscribe": + resp.Result = "true" + return + case "eth_estimateGas": + resp.Error.Code = -32000 + resp.Error.Message = "something went wrong" + } + return + }).WSURL().String() + + ethClient := mustNewChainClient(t, wsURL) + err := ethClient.Dial(ctx) + require.NoError(t, err) + + msg := ethereum.CallMsg{ + From: fromAddress, + To: &toAddress, + Data: []byte("0x00"), + } + sendErr := client.SimulateTransaction(ctx, ethClient, logger.TestSugared(t), "", msg) + require.Equal(t, false, sendErr.IsOutOfCounters()) + }) +} diff --git a/core/chains/evm/config/chain_scoped.go b/core/chains/evm/config/chain_scoped.go index aa13b9a2282..2201831feaf 100644 --- a/core/chains/evm/config/chain_scoped.go +++ b/core/chains/evm/config/chain_scoped.go @@ -20,7 +20,7 @@ import ( func NewTOMLChainScopedConfig(appCfg config.AppConfig, tomlConfig *toml.EVMConfig, lggr logger.Logger) *ChainScoped { return &ChainScoped{ AppConfig: appCfg, - evmConfig: &evmConfig{c: tomlConfig}, + evmConfig: &EVMConfig{C: tomlConfig}, lggr: lggr} } @@ -29,7 +29,7 @@ type ChainScoped struct { config.AppConfig lggr logger.Logger - evmConfig *evmConfig + evmConfig *EVMConfig } func (c *ChainScoped) EVM() EVM { @@ -37,7 +37,7 @@ func (c *ChainScoped) EVM() EVM { } func (c *ChainScoped) Nodes() toml.EVMNodes { - return c.evmConfig.c.Nodes + return c.evmConfig.C.Nodes } func (c *ChainScoped) BlockEmissionIdleWarningThreshold() time.Duration { @@ -62,142 +62,142 @@ func (c *ChainScoped) Validate() (err error) { return } -type evmConfig struct { - c *toml.EVMConfig +type EVMConfig struct { + C *toml.EVMConfig } -func (e *evmConfig) IsEnabled() bool { - return e.c.IsEnabled() +func (e *EVMConfig) IsEnabled() bool { + return e.C.IsEnabled() } -func (e *evmConfig) TOMLString() (string, error) { - return e.c.TOMLString() +func (e *EVMConfig) TOMLString() (string, error) { + return e.C.TOMLString() } -func (e *evmConfig) BalanceMonitor() BalanceMonitor { - return &balanceMonitorConfig{c: e.c.BalanceMonitor} +func (e *EVMConfig) BalanceMonitor() BalanceMonitor { + return &balanceMonitorConfig{c: e.C.BalanceMonitor} } -func (e *evmConfig) Transactions() Transactions { - return &transactionsConfig{c: e.c.Transactions} +func (e *EVMConfig) Transactions() Transactions { + return &transactionsConfig{c: e.C.Transactions} } -func (e *evmConfig) HeadTracker() HeadTracker { - return &headTrackerConfig{c: e.c.HeadTracker} +func (e *EVMConfig) HeadTracker() HeadTracker { + return &headTrackerConfig{c: e.C.HeadTracker} } -func (e *evmConfig) OCR() OCR { - return &ocrConfig{c: e.c.OCR} +func (e *EVMConfig) OCR() OCR { + return &ocrConfig{c: e.C.OCR} } -func (e *evmConfig) OCR2() OCR2 { - return &ocr2Config{c: e.c.OCR2} +func (e *EVMConfig) OCR2() OCR2 { + return &ocr2Config{c: e.C.OCR2} } -func (e *evmConfig) ChainWriter() ChainWriter { - return &chainWriterConfig{c: e.c.ChainWriter} +func (e *EVMConfig) ChainWriter() ChainWriter { + return &chainWriterConfig{c: e.C.ChainWriter} } -func (e *evmConfig) GasEstimator() GasEstimator { - return &gasEstimatorConfig{c: e.c.GasEstimator, blockDelay: e.c.RPCBlockQueryDelay, transactionsMaxInFlight: e.c.Transactions.MaxInFlight, k: e.c.KeySpecific} +func (e *EVMConfig) GasEstimator() GasEstimator { + return &gasEstimatorConfig{c: e.C.GasEstimator, blockDelay: e.C.RPCBlockQueryDelay, transactionsMaxInFlight: e.C.Transactions.MaxInFlight, k: e.C.KeySpecific} } -func (e *evmConfig) AutoCreateKey() bool { - return *e.c.AutoCreateKey +func (e *EVMConfig) AutoCreateKey() bool { + return *e.C.AutoCreateKey } -func (e *evmConfig) BlockBackfillDepth() uint64 { - return uint64(*e.c.BlockBackfillDepth) +func (e *EVMConfig) BlockBackfillDepth() uint64 { + return uint64(*e.C.BlockBackfillDepth) } -func (e *evmConfig) BlockBackfillSkip() bool { - return *e.c.BlockBackfillSkip +func (e *EVMConfig) BlockBackfillSkip() bool { + return *e.C.BlockBackfillSkip } -func (e *evmConfig) LogBackfillBatchSize() uint32 { - return *e.c.LogBackfillBatchSize +func (e *EVMConfig) LogBackfillBatchSize() uint32 { + return *e.C.LogBackfillBatchSize } -func (e *evmConfig) LogPollInterval() time.Duration { - return e.c.LogPollInterval.Duration() +func (e *EVMConfig) LogPollInterval() time.Duration { + return e.C.LogPollInterval.Duration() } -func (e *evmConfig) FinalityDepth() uint32 { - return *e.c.FinalityDepth +func (e *EVMConfig) FinalityDepth() uint32 { + return *e.C.FinalityDepth } -func (e *evmConfig) FinalityTagEnabled() bool { - return *e.c.FinalityTagEnabled +func (e *EVMConfig) FinalityTagEnabled() bool { + return *e.C.FinalityTagEnabled } -func (e *evmConfig) LogKeepBlocksDepth() uint32 { - return *e.c.LogKeepBlocksDepth +func (e *EVMConfig) LogKeepBlocksDepth() uint32 { + return *e.C.LogKeepBlocksDepth } -func (e *evmConfig) BackupLogPollerBlockDelay() uint64 { - return *e.c.BackupLogPollerBlockDelay +func (e *EVMConfig) BackupLogPollerBlockDelay() uint64 { + return *e.C.BackupLogPollerBlockDelay } -func (e *evmConfig) NonceAutoSync() bool { - return *e.c.NonceAutoSync +func (e *EVMConfig) NonceAutoSync() bool { + return *e.C.NonceAutoSync } -func (e *evmConfig) RPCDefaultBatchSize() uint32 { - return *e.c.RPCDefaultBatchSize +func (e *EVMConfig) RPCDefaultBatchSize() uint32 { + return *e.C.RPCDefaultBatchSize } -func (e *evmConfig) BlockEmissionIdleWarningThreshold() time.Duration { - return e.c.NoNewHeadsThreshold.Duration() +func (e *EVMConfig) BlockEmissionIdleWarningThreshold() time.Duration { + return e.C.NoNewHeadsThreshold.Duration() } -func (e *evmConfig) ChainType() commonconfig.ChainType { - if e.c.ChainType == nil { +func (e *EVMConfig) ChainType() commonconfig.ChainType { + if e.C.ChainType == nil { return "" } - return commonconfig.ChainType(*e.c.ChainType) + return commonconfig.ChainType(*e.C.ChainType) } -func (e *evmConfig) ChainID() *big.Int { - return e.c.ChainID.ToInt() +func (e *EVMConfig) ChainID() *big.Int { + return e.C.ChainID.ToInt() } -func (e *evmConfig) MinIncomingConfirmations() uint32 { - return *e.c.MinIncomingConfirmations +func (e *EVMConfig) MinIncomingConfirmations() uint32 { + return *e.C.MinIncomingConfirmations } -func (e *evmConfig) NodePool() NodePool { - return &NodePoolConfig{C: e.c.NodePool} +func (e *EVMConfig) NodePool() NodePool { + return &NodePoolConfig{C: e.C.NodePool} } -func (e *evmConfig) NodeNoNewHeadsThreshold() time.Duration { - return e.c.NoNewHeadsThreshold.Duration() +func (e *EVMConfig) NodeNoNewHeadsThreshold() time.Duration { + return e.C.NoNewHeadsThreshold.Duration() } -func (e *evmConfig) MinContractPayment() *assets.Link { - return e.c.MinContractPayment +func (e *EVMConfig) MinContractPayment() *assets.Link { + return e.C.MinContractPayment } -func (e *evmConfig) FlagsContractAddress() string { - if e.c.FlagsContractAddress == nil { +func (e *EVMConfig) FlagsContractAddress() string { + if e.C.FlagsContractAddress == nil { return "" } - return e.c.FlagsContractAddress.String() + return e.C.FlagsContractAddress.String() } -func (e *evmConfig) LinkContractAddress() string { - if e.c.LinkContractAddress == nil { +func (e *EVMConfig) LinkContractAddress() string { + if e.C.LinkContractAddress == nil { return "" } - return e.c.LinkContractAddress.String() + return e.C.LinkContractAddress.String() } -func (e *evmConfig) OperatorFactoryAddress() string { - if e.c.OperatorFactoryAddress == nil { +func (e *EVMConfig) OperatorFactoryAddress() string { + if e.C.OperatorFactoryAddress == nil { return "" } - return e.c.OperatorFactoryAddress.String() + return e.C.OperatorFactoryAddress.String() } -func (e *evmConfig) LogPrunePageSize() uint32 { - return *e.c.LogPrunePageSize +func (e *EVMConfig) LogPrunePageSize() uint32 { + return *e.C.LogPrunePageSize } diff --git a/core/chains/evm/config/chain_scoped_node_pool.go b/core/chains/evm/config/chain_scoped_node_pool.go index 0796d004cae..6874b412f7f 100644 --- a/core/chains/evm/config/chain_scoped_node_pool.go +++ b/core/chains/evm/config/chain_scoped_node_pool.go @@ -33,3 +33,7 @@ func (n *NodePoolConfig) LeaseDuration() time.Duration { func (n *NodePoolConfig) NodeIsSyncingEnabled() bool { return *n.C.NodeIsSyncingEnabled } + +func (n *NodePoolConfig) FinalizedBlockPollInterval() time.Duration { + return n.C.FinalizedBlockPollInterval.Duration() +} diff --git a/core/chains/evm/config/config.go b/core/chains/evm/config/config.go index ee9c46c14e4..b9ff9ea9f8e 100644 --- a/core/chains/evm/config/config.go +++ b/core/chains/evm/config/config.go @@ -141,6 +141,7 @@ type NodePool interface { SyncThreshold() uint32 LeaseDuration() time.Duration NodeIsSyncingEnabled() bool + FinalizedBlockPollInterval() time.Duration } // TODO BCF-2509 does the chainscopedconfig really need the entire app config? diff --git a/core/chains/evm/config/toml/config.go b/core/chains/evm/config/toml/config.go index 4ad0e6569bb..0f647034162 100644 --- a/core/chains/evm/config/toml/config.go +++ b/core/chains/evm/config/toml/config.go @@ -400,6 +400,7 @@ func (c *Chain) ValidateConfig() (err error) { err = multierr.Append(err, commonconfig.ErrInvalid{Name: "MinIncomingConfirmations", Value: *c.MinIncomingConfirmations, Msg: "must be greater than or equal to 1"}) } + return } @@ -702,12 +703,13 @@ func (t *HeadTracker) setFrom(f *HeadTracker) { } type NodePool struct { - PollFailureThreshold *uint32 - PollInterval *commonconfig.Duration - SelectionMode *string - SyncThreshold *uint32 - LeaseDuration *commonconfig.Duration - NodeIsSyncingEnabled *bool + PollFailureThreshold *uint32 + PollInterval *commonconfig.Duration + SelectionMode *string + SyncThreshold *uint32 + LeaseDuration *commonconfig.Duration + NodeIsSyncingEnabled *bool + FinalizedBlockPollInterval *commonconfig.Duration } func (p *NodePool) setFrom(f *NodePool) { @@ -729,6 +731,9 @@ func (p *NodePool) setFrom(f *NodePool) { if v := f.NodeIsSyncingEnabled; v != nil { p.NodeIsSyncingEnabled = v } + if v := f.FinalizedBlockPollInterval; v != nil { + p.FinalizedBlockPollInterval = v + } } type OCR struct { diff --git a/core/chains/evm/config/toml/defaults/fallback.toml b/core/chains/evm/config/toml/defaults/fallback.toml index 1a1d9b69439..d65d0a1b0c1 100644 --- a/core/chains/evm/config/toml/defaults/fallback.toml +++ b/core/chains/evm/config/toml/defaults/fallback.toml @@ -62,6 +62,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 diff --git a/core/chains/evm/gas/rollups/l1_oracle.go b/core/chains/evm/gas/rollups/l1_oracle.go index e9cdc6b73b1..ae46071cf0d 100644 --- a/core/chains/evm/gas/rollups/l1_oracle.go +++ b/core/chains/evm/gas/rollups/l1_oracle.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/rpc" "github.com/smartcontractkit/chainlink-common/pkg/logger" "github.com/smartcontractkit/chainlink-common/pkg/services" @@ -28,6 +29,12 @@ import ( //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 +} + +//go:generate mockery --quiet --name daPriceReader --output ./mocks/ --case=underscore --structname DAPriceReader +type daPriceReader interface { + GetDAGasPrice(ctx context.Context) (*big.Int, error) } type priceEntry struct { @@ -53,6 +60,8 @@ type l1Oracle struct { gasCostMethod string l1GasCostMethodAbi abi.ABI + priceReader daPriceReader + chInitialised chan struct{} chStop services.StopChan chDone chan struct{} @@ -109,9 +118,23 @@ func IsRollupWithL1Support(chainType config.ChainType) bool { } 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 + } + 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 + switch chainType { case config.ChainArbitrum: l1GasPriceAddress = ArbGasInfoAddress @@ -164,6 +187,8 @@ func NewL1GasOracle(lggr logger.Logger, ethClient ethClient, chainType config.Ch gasCostMethod: gasCostMethod, l1GasCostMethodAbi: l1GasCostMethodAbi, + priceReader: priceReader, + chInitialised: make(chan struct{}), chStop: make(chan struct{}), chDone: make(chan struct{}), @@ -222,13 +247,30 @@ func (o *l1Oracle) refreshWithError() (t *time.Timer, err error) { 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 t, fmt.Errorf("%s: %w", errMsg, err) + return nil, fmt.Errorf("%s: %w", errMsg, err) } b, err = o.client.CallContract(ctx, ethereum.CallMsg{ To: &precompile, @@ -237,20 +279,16 @@ func (o *l1Oracle) refreshWithError() (t *time.Timer, err error) { if err != nil { errMsg := "gas oracle contract call failed" o.logger.Errorf(errMsg) - return t, fmt.Errorf("%s: %w", errMsg, err) + 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 t, fmt.Errorf(errMsg) + return nil, fmt.Errorf(errMsg) } - price := new(big.Int).SetBytes(b) - - o.l1GasPriceMu.Lock() - defer o.l1GasPriceMu.Unlock() - o.l1GasPrice = priceEntry{price: assets.NewWei(price), timestamp: time.Now()} - return + price = new(big.Int).SetBytes(b) + return price, nil } func (o *l1Oracle) GasPrice(_ context.Context) (l1GasPrice *assets.Wei, err error) { diff --git a/core/chains/evm/gas/rollups/l1_oracle_abi.go b/core/chains/evm/gas/rollups/l1_oracle_abi.go index 77ef4d49f3c..dc18e43c98e 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_abi.go +++ b/core/chains/evm/gas/rollups/l1_oracle_abi.go @@ -11,3 +11,7 @@ const GasEstimateL1ComponentAbiString = `[{"inputs":[{"internalType":"address"," // All ABIs found at https://optimistic.etherscan.io/address/0xc0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d3c0d3000f#code const L1BaseFeeAbiString = `[{"inputs":[],"name":"l1BaseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` const GetL1FeeAbiString = `[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"getL1Fee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` + +// ABIs for OP Stack Ecotone GasPriceOracle methods needed to calculated encoded gas price +const OPIsEcotoneAbiString = `[{"inputs":[],"name":"isEcotone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]` +const OPGetL1GasUsedAbiString = `[{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"getL1GasUsed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]` diff --git a/core/chains/evm/gas/rollups/l1_oracle_test.go b/core/chains/evm/gas/rollups/l1_oracle_test.go index 8415e4d7805..4f3b67e2ecf 100644 --- a/core/chains/evm/gas/rollups/l1_oracle_test.go +++ b/core/chains/evm/gas/rollups/l1_oracle_test.go @@ -72,21 +72,11 @@ 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) - l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - require.NoError(t, err) - ethClient := mocks.NewETHClient(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 = l1GasPriceMethodAbi.Pack("l1BaseFee") - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - assert.Nil(t, blockNumber) - }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) + priceReader := mocks.NewDAPriceReader(t) + priceReader.On("GetDAGasPrice", mock.Anything).Return(l1BaseFee, nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainKroma) + oracle := newL1GasOracle(logger.Test(t), nil, config.ChainKroma, priceReader) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(testutils.Context(t)) @@ -97,21 +87,11 @@ 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) - l1GasPriceMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) - require.NoError(t, err) - ethClient := mocks.NewETHClient(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 = l1GasPriceMethodAbi.Pack("l1BaseFee") - require.NoError(t, err) - require.Equal(t, payload, callMsg.Data) - assert.Nil(t, blockNumber) - }).Return(common.BigToHash(l1BaseFee).Bytes(), nil) + priceReader := mocks.NewDAPriceReader(t) + priceReader.On("GetDAGasPrice", mock.Anything).Return(l1BaseFee, nil) - oracle := NewL1GasOracle(logger.Test(t), ethClient, config.ChainOptimismBedrock) + oracle := newL1GasOracle(logger.Test(t), nil, config.ChainOptimismBedrock, priceReader) servicetest.RunHealthy(t, oracle) gasPrice, err := oracle.GasPrice(testutils.Context(t)) diff --git a/core/chains/evm/gas/rollups/mocks/da_price_reader.go b/core/chains/evm/gas/rollups/mocks/da_price_reader.go new file mode 100644 index 00000000000..7758f53e436 --- /dev/null +++ b/core/chains/evm/gas/rollups/mocks/da_price_reader.go @@ -0,0 +1,59 @@ +// 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/eth_client.go index bb0784f8515..e5a28f715ad 100644 --- a/core/chains/evm/gas/rollups/mocks/eth_client.go +++ b/core/chains/evm/gas/rollups/mocks/eth_client.go @@ -9,6 +9,8 @@ import ( ethereum "github.com/ethereum/go-ethereum" mock "github.com/stretchr/testify/mock" + + rpc "github.com/ethereum/go-ethereum/rpc" ) // ETHClient is an autogenerated mock type for the ethClient type @@ -16,6 +18,24 @@ type ETHClient struct { mock.Mock } +// BatchCallContext provides a mock function with given fields: ctx, b +func (_m *ETHClient) 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 +} + // 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) diff --git a/core/chains/evm/gas/rollups/op_price_reader.go b/core/chains/evm/gas/rollups/op_price_reader.go new file mode 100644 index 00000000000..2d3d668ad8b --- /dev/null +++ b/core/chains/evm/gas/rollups/op_price_reader.go @@ -0,0 +1,228 @@ +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/rollups/op_price_reader_test.go b/core/chains/evm/gas/rollups/op_price_reader_test.go new file mode 100644 index 00000000000..dad12a16366 --- /dev/null +++ b/core/chains/evm/gas/rollups/op_price_reader_test.go @@ -0,0 +1,200 @@ +package rollups + +import ( + "fmt" + "math/big" + "strings" + "testing" + + "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/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "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/gas/rollups/mocks" + "github.com/smartcontractkit/chainlink/v2/core/internal/testutils" +) + +func TestDAPriceReader_ReadV1GasPrice(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + isEcotoneError bool + returnBadData bool + }{ + { + name: "calling isEcotone returns false, fetches l1BaseFee", + isEcotoneError: false, + }, + { + name: "calling isEcotone when chain has not made Ecotone upgrade, fetches l1BaseFee", + isEcotoneError: true, + }, + { + name: "calling isEcotone returns bad data, returns error", + isEcotoneError: false, + returnBadData: true, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + l1BaseFee := big.NewInt(100) + oracleAddress := common.HexToAddress("0x1234").String() + + l1BaseFeeMethodAbi, err := abi.JSON(strings.NewReader(L1BaseFeeAbiString)) + require.NoError(t, err) + l1BaseFeeCalldata, err := l1BaseFeeMethodAbi.Pack(OPStackGasOracle_l1BaseFee) + require.NoError(t, err) + + 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) + 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) + require.Equal(t, isEcotoneCalldata, callMsg.Data) + require.Equal(t, oracleAddress, callMsg.To.String()) + assert.Nil(t, blockNumber) + }) + + if tc.returnBadData { + call.Return([]byte{0x2, 0x2}, nil).Once() + } else if tc.isEcotoneError { + call.Return(nil, fmt.Errorf("test error")).Once() + } else { + call.Return(isEcotoneMethodAbi.Methods["isEcotone"].Outputs.Pack(false)).Once() + } + + if !tc.returnBadData { + 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) + require.Equal(t, l1BaseFeeCalldata, callMsg.Data) + require.Equal(t, oracleAddress, callMsg.To.String()) + assert.Nil(t, blockNumber) + }).Return(common.BigToHash(l1BaseFee).Bytes(), nil).Once() + } + + oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + gasPrice, err := oracle.GetDAGasPrice(testutils.Context(t)) + + if tc.returnBadData { + assert.Error(t, err) + } else { + require.NoError(t, err) + assert.Equal(t, l1BaseFee, gasPrice) + } + }) + } +} + +func setupIsEcotone(t *testing.T, oracleAddress string) *mocks.ETHClient { + 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.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) + require.Equal(t, isEcotoneCalldata, callMsg.Data) + require.Equal(t, oracleAddress, callMsg.To.String()) + assert.Nil(t, blockNumber) + }).Return(isEcotoneMethodAbi.Methods["isEcotone"].Outputs.Pack(true)).Once() + + return ethClient +} + +func TestDAPriceReader_ReadEcotoneGasPrice(t *testing.T) { + l1BaseFee := big.NewInt(100) + oracleAddress := common.HexToAddress("0x1234").String() + + t.Parallel() + + t.Run("correctly fetches weighted gas price if chain has upgraded to Ecotone", func(t *testing.T) { + ethClient := setupIsEcotone(t, oracleAddress) + getL1GasUsedMethodAbi, err := abi.JSON(strings.NewReader(OPGetL1GasUsedAbiString)) + require.NoError(t, err) + getL1GasUsedCalldata, err := getL1GasUsedMethodAbi.Pack(OPStackGasOracle_getL1GasUsed, []byte{0x1}) + require.NoError(t, err) + + getL1FeeMethodAbi, err := abi.JSON(strings.NewReader(GetL1FeeAbiString)) + require.NoError(t, err) + getL1FeeCalldata, err := getL1FeeMethodAbi.Pack(OPStackGasOracle_getL1Fee, []byte{0x1}) + require.NoError(t, err) + + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + require.Equal(t, 2, len(rpcElements)) + + 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, "latest", rE.Args[1]) + } + + require.Equal(t, hexutil.Bytes(getL1GasUsedCalldata), rpcElements[0].Args[0].(map[string]interface{})["data"]) + require.Equal(t, hexutil.Bytes(getL1FeeCalldata), rpcElements[1].Args[0].(map[string]interface{})["data"]) + + res1 := common.BigToHash(big.NewInt(1)).Hex() + res2 := common.BigToHash(l1BaseFee).Hex() + rpcElements[0].Result = &res1 + rpcElements[1].Result = &res2 + }).Return(nil).Once() + + oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + gasPrice, err := oracle.GetDAGasPrice(testutils.Context(t)) + require.NoError(t, err) + assert.Equal(t, l1BaseFee, gasPrice) + }) + + t.Run("fetching Ecotone price but rpc returns bad data", func(t *testing.T) { + ethClient := setupIsEcotone(t, oracleAddress) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + var badData = "zzz" + rpcElements[0].Result = &badData + rpcElements[1].Result = &badData + }).Return(nil).Once() + + oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + _, err := oracle.GetDAGasPrice(testutils.Context(t)) + assert.Error(t, err) + }) + + t.Run("fetching Ecotone price but rpc parent call errors", func(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) + _, err := oracle.GetDAGasPrice(testutils.Context(t)) + assert.Error(t, err) + }) + + t.Run("fetching Ecotone price but one of the sub rpc call errors", func(t *testing.T) { + ethClient := setupIsEcotone(t, oracleAddress) + ethClient.On("BatchCallContext", mock.Anything, mock.IsType([]rpc.BatchElem{})).Run(func(args mock.Arguments) { + rpcElements := args.Get(1).([]rpc.BatchElem) + res := common.BigToHash(l1BaseFee).Hex() + rpcElements[0].Result = &res + rpcElements[1].Error = fmt.Errorf("revert") + }).Return(nil).Once() + + oracle := newOPPriceReader(logger.Test(t), ethClient, config.ChainOptimismBedrock, oracleAddress) + _, err := oracle.GetDAGasPrice(testutils.Context(t)) + assert.Error(t, err) + }) +} diff --git a/core/chains/evm/logpoller/disabled.go b/core/chains/evm/logpoller/disabled.go index 8287aed22a4..0f8faba2695 100644 --- a/core/chains/evm/logpoller/disabled.go +++ b/core/chains/evm/logpoller/disabled.go @@ -21,6 +21,10 @@ func (disabled) Start(ctx context.Context) error { return ErrDisabled } func (disabled) Close() error { return ErrDisabled } +func (disabled) Healthy() error { + return ErrDisabled +} + func (disabled) Ready() error { return ErrDisabled } func (disabled) HealthReport() map[string]error { diff --git a/core/chains/evm/logpoller/log_poller.go b/core/chains/evm/logpoller/log_poller.go index ffcfa96b4d2..490a104aa05 100644 --- a/core/chains/evm/logpoller/log_poller.go +++ b/core/chains/evm/logpoller/log_poller.go @@ -11,6 +11,7 @@ import ( "sort" "strings" "sync" + "sync/atomic" "time" "github.com/ethereum/go-ethereum" @@ -34,6 +35,7 @@ import ( //go:generate mockery --quiet --name LogPoller --output ./mocks/ --case=underscore --structname LogPoller --filename log_poller.go type LogPoller interface { services.Service + Healthy() error Replay(ctx context.Context, fromBlock int64) error ReplayAsync(fromBlock int64) RegisterFilter(ctx context.Context, filter Filter) error @@ -92,6 +94,7 @@ var ( ErrReplayRequestAborted = pkgerrors.New("aborted, replay request cancelled") ErrReplayInProgress = pkgerrors.New("replay request cancelled, but replay is already in progress") ErrLogPollerShutdown = pkgerrors.New("replay aborted due to log poller shutdown") + ErrFinalityViolated = pkgerrors.New("finality violated") ) type logPoller struct { @@ -120,6 +123,12 @@ type logPoller struct { ctx context.Context cancel context.CancelFunc wg sync.WaitGroup + // This flag is raised whenever the log poller detects that the chain's finality has been violated. + // It can happen when reorg is deeper than the latest finalized block that LogPoller saw in a previous PollAndSave tick. + // Usually the only way to recover is to manually remove the offending logs and block from the database. + // LogPoller keeps running in infinite loop, so whenever the invalid state is removed from the database it should + // recover automatically without needing to restart the LogPoller. + finalityViolated *atomic.Bool } type Opts struct { @@ -163,6 +172,7 @@ func NewLogPoller(orm ORM, ec Client, lggr logger.Logger, opts Opts) *logPoller logPrunePageSize: opts.LogPrunePageSize, filters: make(map[string]Filter), filterDirty: true, // Always build Filter on first call to cache an empty filter if nothing registered yet. + finalityViolated: new(atomic.Bool), } } @@ -466,6 +476,13 @@ func (lp *logPoller) Close() error { }) } +func (lp *logPoller) Healthy() error { + if lp.finalityViolated.Load() { + return ErrFinalityViolated + } + return nil +} + func (lp *logPoller) Name() string { return lp.lggr.Name() } @@ -786,7 +803,13 @@ func (lp *logPoller) backfill(ctx context.Context, start, end int64) error { // 1. Find the LCA by following parent hashes. // 2. Delete all logs and blocks after the LCA // 3. Return the LCA+1, i.e. our new current (unprocessed) block. -func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, currentBlockNumber int64, currentBlock *evmtypes.Head) (*evmtypes.Head, error) { +func (lp *logPoller) getCurrentBlockMaybeHandleReorg(ctx context.Context, currentBlockNumber int64, currentBlock *evmtypes.Head) (head *evmtypes.Head, err error) { + defer func() { + if err == nil { + lp.finalityViolated.Store(false) + } + }() + var err1 error if currentBlock == nil { // If we don't have the current block already, lets get it. @@ -1012,6 +1035,7 @@ func (lp *logPoller) findBlockAfterLCA(ctx context.Context, current *evmtypes.He lp.lggr.Criticalw("Reorg greater than finality depth detected", "finalityTag", lp.useFinalityTag, "current", current.Number, "latestFinalized", latestFinalizedBlockNumber) rerr := pkgerrors.New("Reorg greater than finality depth") lp.SvcErrBuffer.Append(rerr) + lp.finalityViolated.Store(true) return nil, rerr } diff --git a/core/chains/evm/logpoller/log_poller_test.go b/core/chains/evm/logpoller/log_poller_test.go index a8301a51e47..6605272c672 100644 --- a/core/chains/evm/logpoller/log_poller_test.go +++ b/core/chains/evm/logpoller/log_poller_test.go @@ -1040,6 +1040,93 @@ func TestLogPoller_PollAndSaveLogs(t *testing.T) { } } +func TestLogPoller_ReorgDeeperThanFinality(t *testing.T) { + tests := []struct { + name string + finalityDepth int64 + finalityTag bool + }{ + { + name: "fixed finality depth without finality tag", + finalityDepth: 1, + finalityTag: false, + }, + { + name: "chain finality in use", + finalityDepth: 0, + finalityTag: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + th := SetupTH(t, logpoller.Opts{ + UseFinalityTag: tt.finalityTag, + FinalityDepth: tt.finalityDepth, + BackfillBatchSize: 3, + RpcBatchSize: 2, + KeepFinalizedBlocksDepth: 1000, + BackupPollerBlockDelay: 100, + }) + // Set up a log poller listening for log emitter logs. + err := th.LogPoller.RegisterFilter(testutils.Context(t), logpoller.Filter{ + Name: "Test Emitter", + EventSigs: []common.Hash{EmitterABI.Events["Log1"].ID}, + Addresses: []common.Address{th.EmitterAddress1}, + }) + require.NoError(t, err) + + // Test scenario + // Chain gen <- 1 <- 2 <- 3 (finalized) <- 4 (L1_1) + _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(1)}) + require.NoError(t, err) + th.Client.Commit() + th.Client.Commit() + th.Client.Commit() + markBlockAsFinalized(t, th, 3) + + // Polling should get us the L1 log. + firstPoll := th.PollAndSaveLogs(testutils.Context(t), 1) + assert.Equal(t, int64(5), firstPoll) + assert.NoError(t, th.LogPoller.Healthy()) + + // Fork deeper than finality depth + // Chain gen <- 1 <- 2 <- 3 (finalized) <- 4 (L1_1) + // \ 2' <- 3' <- 4' <- 5' <- 6' (finalized) <- 7' <- 8' <- 9' <- 10' (L1_2) + lca, err := th.Client.BlockByNumber(testutils.Context(t), big.NewInt(1)) + require.NoError(t, err) + require.NoError(t, th.Client.Fork(testutils.Context(t), lca.Hash())) + + // Create 2' + _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(2)}) + require.NoError(t, err) + th.Client.Commit() + + // Create 3-10 + for i := 3; i < 10; i++ { + _, err = th.Emitter1.EmitLog1(th.Owner, []*big.Int{big.NewInt(int64(i))}) + require.NoError(t, err) + th.Client.Commit() + } + markBlockAsFinalized(t, th, 6) + + secondPoll := th.PollAndSaveLogs(testutils.Context(t), firstPoll) + assert.Equal(t, firstPoll, secondPoll) + assert.Equal(t, logpoller.ErrFinalityViolated, th.LogPoller.Healthy()) + + // Manually remove latest block from the log poller to bring it back to life + // LogPoller should be healthy again after first poll + // Chain gen <- 1 + // \ 2' <- 3' <- 4' <- 5' <- 6' (finalized) <- 7' <- 8' <- 9' <- 10' (L1_2) + require.NoError(t, th.ORM.DeleteLogsAndBlocksAfter(testutils.Context(t), 2)) + // Poll from latest + recoveryPoll := th.PollAndSaveLogs(testutils.Context(t), 1) + assert.Equal(t, int64(10), recoveryPoll) + assert.NoError(t, th.LogPoller.Healthy()) + }) + } +} + func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { t.Parallel() @@ -1089,6 +1176,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { // Polling should get us the L1 log. newStart := th.PollAndSaveLogs(testutils.Context(t), 1) + assert.NoError(t, th.LogPoller.Healthy()) assert.Equal(t, int64(3), newStart) // Check that L1_1 has a proper data payload lgs, err := th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) @@ -1115,6 +1203,7 @@ func TestLogPoller_PollAndSaveLogsDeepReorg(t *testing.T) { newStart = th.PollAndSaveLogs(testutils.Context(t), newStart) assert.Equal(t, int64(10), newStart) + assert.NoError(t, th.LogPoller.Healthy()) // Expect L1_2 to be properly updated lgs, err = th.ORM.SelectLogsByBlockRange(testutils.Context(t), 2, 2) diff --git a/core/chains/evm/logpoller/mocks/log_poller.go b/core/chains/evm/logpoller/mocks/log_poller.go index 2bf24881405..ea129dfc4ef 100644 --- a/core/chains/evm/logpoller/mocks/log_poller.go +++ b/core/chains/evm/logpoller/mocks/log_poller.go @@ -105,6 +105,24 @@ func (_m *LogPoller) HealthReport() map[string]error { return r0 } +// Healthy provides a mock function with given fields: +func (_m *LogPoller) Healthy() error { + ret := _m.Called() + + if len(ret) == 0 { + panic("no return value specified for Healthy") + } + + var r0 error + if rf, ok := ret.Get(0).(func() error); ok { + r0 = rf() + } else { + r0 = ret.Error(0) + } + + return r0 +} + // IndexedLogs provides a mock function with given fields: ctx, eventSig, address, topicIndex, topicValues, confs func (_m *LogPoller) IndexedLogs(ctx context.Context, eventSig common.Hash, address common.Address, topicIndex int, topicValues []common.Hash, confs logpoller.Confirmations) ([]logpoller.Log, error) { ret := _m.Called(ctx, eventSig, address, topicIndex, topicValues, confs) diff --git a/core/chains/evm/types/models.go b/core/chains/evm/types/models.go index 4aeaec511d1..1bf47f84726 100644 --- a/core/chains/evm/types/models.go +++ b/core/chains/evm/types/models.go @@ -461,7 +461,7 @@ var WeiPerEth = new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil) // ChainlinkFulfilledTopic is the signature for the event emitted after calling // ChainlinkClient.validateChainlinkCallback(requestId). See -// ../../contracts/src/v0.6/ChainlinkClient.sol +// ../../contracts/src/v0.8/ChainlinkClient.sol var ChainlinkFulfilledTopic = utils.MustHash("ChainlinkFulfilled(bytes32)") // ReceiptIndicatesRunLogFulfillment returns true if this tx receipt is the result of a diff --git a/core/chains/legacyevm/chain.go b/core/chains/legacyevm/chain.go index 830a1198258..1066eeecbea 100644 --- a/core/chains/legacyevm/chain.go +++ b/core/chains/legacyevm/chain.go @@ -212,13 +212,13 @@ func NewTOMLChain(ctx context.Context, chain *toml.EVMConfig, opts ChainRelayExt } func newChain(ctx context.Context, cfg *evmconfig.ChainScoped, nodes []*toml.Node, opts ChainRelayExtenderConfig) (*chain, error) { - chainID, chainType := cfg.EVM().ChainID(), cfg.EVM().ChainType() + chainID := cfg.EVM().ChainID() l := opts.Logger var client evmclient.Client if !cfg.EVMRPCEnabled() { client = evmclient.NewNullClient(chainID, l) } else if opts.GenEthClient == nil { - client = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM().NodeNoNewHeadsThreshold(), l, chainID, chainType, nodes) + client = evmclient.NewEvmClient(cfg.EVM().NodePool(), cfg.EVM(), l, chainID, nodes) } else { client = opts.GenEthClient(chainID) } diff --git a/core/cmd/shell_test.go b/core/cmd/shell_test.go index f265d5f4787..d57cfe1f645 100644 --- a/core/cmd/shell_test.go +++ b/core/cmd/shell_test.go @@ -17,6 +17,7 @@ import ( "github.com/stretchr/testify/require" "github.com/urfave/cli" + commoncfg "github.com/smartcontractkit/chainlink-common/pkg/config" "github.com/smartcontractkit/chainlink-solana/pkg/solana" solcfg "github.com/smartcontractkit/chainlink-solana/pkg/solana/config" "github.com/smartcontractkit/chainlink-starknet/relayer/pkg/chainlink/config" @@ -474,22 +475,25 @@ func TestSetupStarkNetRelayer(t *testing.T) { tConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Starknet = stkcfg.TOMLConfigs{ &stkcfg.TOMLConfig{ - ChainID: ptr[string]("starknet-id-1"), - Enabled: ptr(true), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("starknet-id-1"), + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, &stkcfg.TOMLConfig{ - ChainID: ptr[string]("starknet-id-2"), - Enabled: ptr(true), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("starknet-id-2"), + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, &stkcfg.TOMLConfig{ - ChainID: ptr[string]("disabled-starknet-id-1"), - Enabled: ptr(false), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("disabled-starknet-id-1"), + Enabled: ptr(false), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, } }) @@ -497,10 +501,11 @@ func TestSetupStarkNetRelayer(t *testing.T) { t2Config := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Starknet = stkcfg.TOMLConfigs{ &stkcfg.TOMLConfig{ - ChainID: ptr[string]("starknet-id-3"), - Enabled: ptr(true), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("starknet-id-3"), + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, } }) @@ -534,16 +539,18 @@ func TestSetupStarkNetRelayer(t *testing.T) { duplicateConfig := configtest.NewGeneralConfig(t, func(c *chainlink.Config, s *chainlink.Secrets) { c.Starknet = stkcfg.TOMLConfigs{ &stkcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("dupe"), + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, &stkcfg.TOMLConfig{ - ChainID: ptr[string]("dupe"), - Enabled: ptr(true), - Chain: stkcfg.Chain{}, - Nodes: []*config.Node{}, + ChainID: ptr[string]("dupe"), + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + Nodes: []*config.Node{}, + FeederURL: commoncfg.MustParseURL("https://feeder.url"), }, } }) diff --git a/core/config/docs/chains-evm.toml b/core/config/docs/chains-evm.toml index dcf2f6e688e..dd63edaf694 100644 --- a/core/config/docs/chains-evm.toml +++ b/core/config/docs/chains-evm.toml @@ -344,7 +344,14 @@ LeaseDuration = '0s' # Default # # Set true to enable this check NodeIsSyncingEnabled = false # Default - +# FinalizedBlockPollInterval controls how often to poll RPC for new finalized blocks. +# The finalized block is only used to report to the `pool_rpc_node_highest_finalized_block` metric. We plan to use it +# in RPCs health assessment in the future. +# If `FinalityTagEnabled = false`, poll is not performed and `pool_rpc_node_highest_finalized_block` is +# reported based on latest block and finality depth. +# +# Set to 0 to disable. +FinalizedBlockPollInterval = '5s' # Default [EVM.OCR] # ContractConfirmations sets `OCR.ContractConfirmations` for this EVM chain. ContractConfirmations = 4 # Default diff --git a/core/config/docs/chains-starknet.toml b/core/config/docs/chains-starknet.toml index 8694290a7d6..4ea2647a72d 100644 --- a/core/config/docs/chains-starknet.toml +++ b/core/config/docs/chains-starknet.toml @@ -1,6 +1,8 @@ [[Starknet]] # ChainID is the Starknet chain ID. ChainID = 'foobar' # Example +# FeederURL is required to get tx metadata (that the RPC can't) +FeederURL = 'http://feeder.url' # Example # Enabled enables this chain. Enabled = true # Default # OCR2CachePollPeriod is the rate to poll for the OCR2 state cache. @@ -19,3 +21,5 @@ ConfirmationPoll = '5s' # Default Name = 'primary' # Example # URL is the base HTTP(S) endpoint for this node. URL = 'http://stark.node' # Example +# APIKey Header is optional and only required for Nethermind RPCs +APIKey = 'key' # Example diff --git a/core/gethwrappers/README.md b/core/gethwrappers/README.md index 00ba8c31b20..04a029cb532 100644 --- a/core/gethwrappers/README.md +++ b/core/gethwrappers/README.md @@ -22,10 +22,10 @@ might be worthwhile to generate the wrappers using a static container with abigen and solc, which will complete much faster. E.g. ``` - abigen -sol ../../contracts/src/v0.6/VRFAll.sol -pkg vrf -out solidity_interfaces.go + abigen -sol ../../contracts/src/v0.8/vrf/VRF.sol -pkg vrf -out solidity_interfaces.go ``` -where VRFAll.sol simply contains `import "contract_path";` instructions for +where VRF.sol simply contains `import "contract_path";` instructions for all the contracts you wish to target. This runs in about 0.25 seconds in my hands. 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 6ec940e7d4f..a19cef75d93 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 @@ -44,8 +44,8 @@ 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\":\"int256\",\"name\":\"available\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"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\":\"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\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"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\":[{\"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\":[],\"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\"}]", - Bin: "0x6101806040523480156200001257600080fd5b506040516200621e3803806200621e83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615afd620007216000396000818160c4015261011a015260005050600061243e0152600081816119000152611c19015260006125720152600061379701526000612656015260005050615afd6000f3fe608060405260043610620000c25760003560e01c80638e86139b1162000073578063c80480221162000055578063c80480221462000261578063f2fde38b1462000286578063f7d334ba14620002ab57620000c2565b80638e86139b1462000208578063c62cf684146200022d57620000c2565b806379ba509711620000a957806379ba5097146200019e57806385c1b0ba14620001b65780638da5cb5b14620001db57620000c2565b8063349e8cca146200010a57806371791aa01462000164575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e80801562000103573d6000f35b3d6000fd5b005b3480156200011757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200017157600080fd5b506200018962000183366004620042ee565b620002d0565b6040516200015b9796959493929190620043da565b348015620001ab57600080fd5b506200010862000a59565b348015620001c357600080fd5b5062000108620001d53660046200448f565b62000b5c565b348015620001e857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166200013a565b3480156200021557600080fd5b50620001086200022736600462004568565b620017c3565b3480156200023a57600080fd5b50620002526200024c366004620045d3565b62001b4b565b6040519081526020016200015b565b3480156200026e57600080fd5b506200010862000280366004620046c8565b62001ef8565b3480156200029357600080fd5b5062000108620002a5366004620046e2565b620023d0565b348015620002b857600080fd5b5062000189620002ca366004620046c8565b620023e8565b600060606000806000806000620002e662002426565b6000620002f38a62002498565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a0015115620006b85750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff16945085935083925062000a4d915050565b606083015163ffffffff90811614620007045750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff16945085935083925062000a4d915050565b825115620007455750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff16945085935083925062000a4d915050565b62000750846200254e565b809450819850829950505050620007778e858786604001518b8b888a610100015162002756565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff161015620007db5750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff16945085935083925062000a4d915050565b50506000620007ec8d858e62002ad8565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200086a91906200470f565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff1684604051620008ac91906200472f565b60006040518083038160008787f1925050503d8060008114620008ec576040519150601f19603f3d011682016040523d82523d6000602084013e620008f1565b606091505b50915091505a62000903908b6200477c565b9950816200098d576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156200096b5750506040805160208101825260008082529390910151929b509950600898505063ffffffff16945062000a4d915050565b604090930151929a50600399505063ffffffff909116955062000a4d92505050565b80806020019051810190620009a39190620047ed565b909d509b508c620009df5750506040805160208101825260008082529390910151929b509950600498505063ffffffff16945062000a4d915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101562000a3b5750506040805160208101825260008082529390910151929b509950600598505063ffffffff16945062000a4d915050565b5050506040015163ffffffff16945050505b92959891949750929550565b60015473ffffffffffffffffffffffffffffffffffffffff16331462000ae0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000b9b5762000b9b620043ab565b1415801562000be75750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000be45762000be4620043ab565b14155b1562000c1f576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff1662000c6f576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000cab576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905260008467ffffffffffffffff81111562000d115762000d1162004174565b60405190808252806020026020018201604052801562000d3b578160200160208202803683370190505b50905060008567ffffffffffffffff81111562000d5c5762000d5c62004174565b60405190808252806020026020018201604052801562000df357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018162000d7b5790505b50905060008667ffffffffffffffff81111562000e145762000e1462004174565b60405190808252806020026020018201604052801562000e4957816020015b606081526020019060019003908162000e335790505b50905060008767ffffffffffffffff81111562000e6a5762000e6a62004174565b60405190808252806020026020018201604052801562000e9f57816020015b606081526020019060019003908162000e895790505b50905060008867ffffffffffffffff81111562000ec05762000ec062004174565b60405190808252806020026020018201604052801562000ef557816020015b606081526020019060019003908162000edf5790505b50905060005b898110156200159b578a8a8281811062000f195762000f196200483a565b60209081029290920135600081815260048452604090819020815161012081018352815460ff8082161515835261010080830490911615159783019790975263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169381019390935299509097506200103690508862002cc8565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015290911690631a5da6c890602401600060405180830381600087803b158015620010a657600080fd5b505af1158015620010bb573d6000803e3d6000fd5b5050505086858281518110620010d557620010d56200483a565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168682815181106200112957620011296200483a565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015260008981526007909152604090208054620011689062004869565b80601f0160208091040260200160405190810160405280929190818152602001828054620011969062004869565b8015620011e75780601f10620011bb57610100808354040283529160200191620011e7565b820191906000526020600020905b815481529060010190602001808311620011c957829003601f168201915b50505050508482815181106200120157620012016200483a565b6020026020010181905250601d600089815260200190815260200160002080546200122c9062004869565b80601f01602080910402602001604051908101604052809291908181526020018280546200125a9062004869565b8015620012ab5780601f106200127f57610100808354040283529160200191620012ab565b820191906000526020600020905b8154815290600101906020018083116200128d57829003601f168201915b5050505050838281518110620012c557620012c56200483a565b6020026020010181905250601e60008981526020019081526020016000208054620012f09062004869565b80601f01602080910402602001604051908101604052809291908181526020018280546200131e9062004869565b80156200136f5780601f1062001343576101008083540402835291602001916200136f565b820191906000526020600020905b8154815290600101906020018083116200135157829003601f168201915b50505050508282815181106200138957620013896200483a565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560079092529081206200140f9162004110565b6000888152601d60205260408120620014289162004110565b6000888152601e60205260408120620014419162004110565b600088815260066020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556200148260028962002d7f565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8b16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a260c087015161010088015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205462001531916bffffffffffffffffffffffff16906200477c565b6101008801805173ffffffffffffffffffffffffffffffffffffffff90811660009081526021602052604090209290925560c08901519051620015869216908b906bffffffffffffffffffffffff1662002d96565b806200159281620048be565b91505062000efb565b5060008a8a868167ffffffffffffffff811115620015bd57620015bd62004174565b604051908082528060200260200182016040528015620015e7578160200160208202803683370190505b50898888886040516020016200160598979695949392919062004a7e565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808d1693638e86139b939091169163c71249ab91600391869163aab9edd69160048083019260209291908290030181865afa158015620016b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016dd919062004b5d565b866040518463ffffffff1660e01b8152600401620016fe9392919062004b82565b600060405180830381865afa1580156200171c573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262001764919081019062004ba9565b6040518263ffffffff1660e01b815260040162001782919062004be2565b600060405180830381600087803b1580156200179d57600080fd5b505af1158015620017b2573d6000803e3d6000fd5b505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620017ec57620017ec620043ab565b141580156200182257506003336000908152601c602052604090205460ff1660038111156200181f576200181f620043ab565b14155b156200185a576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808080808062001870888a018a62004efa565b965096509650965096509650965060005b875181101562001b3f57600073ffffffffffffffffffffffffffffffffffffffff16878281518110620018b857620018b86200483a565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff1603620019cc57858181518110620018f557620018f56200483a565b6020026020010151307f00000000000000000000000000000000000000000000000000000000000000006040516200192d906200414f565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001977573d6000803e3d6000fd5b508782815181106200198d576200198d6200483a565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001a84888281518110620019e557620019e56200483a565b602002602001015188838151811062001a025762001a026200483a565b602002602001015187848151811062001a1f5762001a1f6200483a565b602002602001015187858151811062001a3c5762001a3c6200483a565b602002602001015187868151811062001a595762001a596200483a565b602002602001015187878151811062001a765762001a766200483a565b602002602001015162002e2a565b87818151811062001a995762001a996200483a565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a7188838151811062001ad75762001ad76200483a565b602002602001015160c001513360405162001b229291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a28062001b3681620048be565b91505062001881565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff16331480159062001b7f575062001b7d60093362003347565b155b1562001bb7576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b62001c06576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001c118762003377565b905060008a307f000000000000000000000000000000000000000000000000000000000000000060405162001c46906200414f565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001c90573d6000803e3d6000fd5b50905062001d81826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062002e2a9050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c62001db9836200502b565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b60405162001e3292919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d878760405162001e6e92919062005051565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d56648560405162001ea8919062004be2565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf48508460405162001ee2919062004be2565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911691810191909152906200201c60005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa158015620020be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020e491906200509e565b9050836060015163ffffffff166000036200212b576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462002170576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015620021a3575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15620021db576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82620021f157620021ee603282620050b8565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff909216919091179091556200224e90600290879062002d7f16565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff161015620022c15760a08501516200228f9084620050ce565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff161115620022c1575060c08401515b808560c00151620022d39190620050ce565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205462002365918316906200477c565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b620023da62003616565b620023e58162003699565b50565b6000606060008060008060006200240f8860405180602001604052806000815250620002d0565b959e949d50929b5090995097509550909350915050565b3273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161462002496576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000818160045b600f8110156200252d577fff000000000000000000000000000000000000000000000000000000000000008216838260208110620024e157620024e16200483a565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146200251857506000949350505050565b806200252481620048be565b9150506200249f565b5081600f1a6001811115620025465762002546620043ab565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015620025dc573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062002602919062005111565b50945090925050506000811315806200261a57508142105b806200263f57508280156200263f57506200263682426200477c565b8463ffffffff16105b156200265057601954965062002654565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015620026c0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620026e6919062005111565b5094509092505050600081131580620026fe57508142105b806200272357508280156200272357506200271a82426200477c565b8463ffffffff16105b156200273457601a54955062002738565b8095505b8686620027458a62003790565b965096509650505050509193909250565b6000808080896001811115620027705762002770620043ab565b0362002780575061ea60620027da565b6001896001811115620027975762002797620043ab565b03620027a8575062014c08620027da565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a608001516001620027ef919062005166565b620027ff9060ff16604062005182565b6018546200282f906103a49074010000000000000000000000000000000000000000900463ffffffff16620050b8565b6200283b9190620050b8565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa158015620028ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028d391906200519c565b90925090508183620028e7836018620050b8565b620028f3919062005182565b60808f01516200290590600162005166565b620029169060ff166115e062005182565b620029229190620050b8565b6200292e9190620050b8565b6200293a9085620050b8565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa158015620029ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029d491906200509e565b8d6060015161ffff16620029e9919062005182565b94505050506000620029fc8b866200388a565b60008d815260046020526040902054909150610100900460ff161562002a625760008c81526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845284529151909116908201525b600062002ab28c6040518061010001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a815260200185815260200160001515815250620039e5565b6020810151815191925062002ac791620051c1565b9d9c50505050505050505050505050565b6060600083600181111562002af15762002af1620043ab565b0362002bbe576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009162002b39916024016200528c565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905062002cc1565b600183600181111562002bd55762002bd5620043ab565b03620027a85760008280602001905181019062002bf3919062005303565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009162002c3a91849160240162005417565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152915062002cc19050565b9392505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462002d26576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614620023e5576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002d8d838362003bdb565b90505b92915050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262002e2590849062003cdf565b505050565b601454760100000000000000000000000000000000000000000000900460ff161562002e82576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562002ee7576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062002f2d5750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562002f65576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562002fd0576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602052604090205467010000000000000090041662003040576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508260076000888152602001908152602001600020908162003285919062005531565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620032d0916bffffffffffffffffffffffff1690620050b8565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d90522062003315838262005531565b506000868152601e6020526040902062003330828262005531565b506200333e60028762003df2565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562002d8d565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa158015620033fb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200342191906200509e565b6200342d91906200477c565b6040518263ffffffff1660e01b81526004016200344c91815260200190565b602060405180830381865afa1580156200346a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200349091906200509e565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f811015620035a457838282815181106200356057620035606200483a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806200359b81620048be565b91505062003540565b50846001811115620035ba57620035ba620043ab565b60f81b81600f81518110620035d357620035d36200483a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053506200360d8162005658565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462002496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000ad7565b3373ffffffffffffffffffffffffffffffffffffffff8216036200371a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000ad7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801562003801573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003827919062005111565b509350509250506000821315806200383e57508042105b806200387257506000846040015162ffffff161180156200387257506200386681426200477c565b846040015162ffffff16105b1562003883575050601b5492915050565b5092915050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa1580156200394d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003973919062005111565b509350509250506000821315806200398a57508042105b80620039be57506000866040015162ffffff16118015620039be5750620039b281426200477c565b866040015162ffffff16105b15620039d45760018301546040850152620039dc565b604084018290525b50505092915050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff16836060015162003a25919062005182565b90508260e00151801562003a385750803a105b1562003a4157503a5b60008360a0015184604001518560200151866000015162003a639190620050b8565b62003a6f908562005182565b62003a7b9190620050b8565b62003a87919062005182565b905062003aa98460c00151604001518262003aa391906200569b565b62003e00565b6bffffffffffffffffffffffff168352608084015162003acf9062003aa390836200569b565b6bffffffffffffffffffffffff16604084015260c08401516020015160009062003b089062ffffff16683635c9adc5dea0000062005182565b9050600081633b9aca008760a001518860c001516000015163ffffffff1689604001518a600001518962003b3d919062005182565b62003b499190620050b8565b62003b55919062005182565b62003b61919062005182565b62003b6d91906200569b565b62003b799190620050b8565b905062003b958660c00151604001518262003aa391906200569b565b6bffffffffffffffffffffffff166020860152608086015162003bbe9062003aa390836200569b565b6bffffffffffffffffffffffff1660608601525050505092915050565b6000818152600183016020526040812054801562003cd457600062003c026001836200477c565b855490915060009062003c18906001906200477c565b905081811462003c8457600086600001828154811062003c3c5762003c3c6200483a565b906000526020600020015490508087600001848154811062003c625762003c626200483a565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062003c985762003c98620056d7565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062002d90565b600091505062002d90565b600062003d43826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662003ea49092919063ffffffff16565b80519091501562002e25578080602001905181019062003d64919062005706565b62002e25576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000ad7565b600062002d8d838362003eb5565b60006bffffffffffffffffffffffff82111562003ea0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f3620626974730000000000000000000000000000000000000000000000000000606482015260840162000ad7565b5090565b606062002546848460008562003f07565b600081815260018301602052604081205462003efe5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562002d90565b50600062002d90565b60608247101562003f9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000ad7565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162003fc691906200472f565b60006040518083038185875af1925050503d806000811462004005576040519150601f19603f3d011682016040523d82523d6000602084013e6200400a565b606091505b50915091506200401d8783838762004028565b979650505050505050565b60608315620040c3578251600003620040bb5773ffffffffffffffffffffffffffffffffffffffff85163b620040bb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000ad7565b508162002546565b620025468383815115620040da5781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000ad7919062004be2565b5080546200411e9062004869565b6000825580601f106200412f575050565b601f016020900490600052602060002090810190620023e591906200415d565b6103ca806200572783390190565b5b8082111562003ea057600081556001016200415e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715620041ca57620041ca62004174565b60405290565b604051610100810167ffffffffffffffff81118282101715620041ca57620041ca62004174565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171562004241576200424162004174565b604052919050565b600067ffffffffffffffff82111562004266576200426662004174565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620042a457600080fd5b8135620042bb620042b58262004249565b620041f7565b818152846020838601011115620042d157600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156200430257600080fd5b82359150602083013567ffffffffffffffff8111156200432157600080fd5b6200432f8582860162004292565b9150509250929050565b60005b83811015620043565781810151838201526020016200433c565b50506000910152565b600081518084526200437981602086016020860162004339565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b871515815260e060208201526000620043f760e08301896200435f565b9050600a871062004431577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201969096526060810194909452608084019290925260a083015260c09091015292915050565b73ffffffffffffffffffffffffffffffffffffffff81168114620023e557600080fd5b80356200448a816200445a565b919050565b600080600060408486031215620044a557600080fd5b833567ffffffffffffffff80821115620044be57600080fd5b818601915086601f830112620044d357600080fd5b813581811115620044e357600080fd5b8760208260051b8501011115620044f957600080fd5b6020928301955093505084013562004511816200445a565b809150509250925092565b60008083601f8401126200452f57600080fd5b50813567ffffffffffffffff8111156200454857600080fd5b6020830191508360208285010111156200456157600080fd5b9250929050565b600080602083850312156200457c57600080fd5b823567ffffffffffffffff8111156200459457600080fd5b620045a2858286016200451c565b90969095509350505050565b803563ffffffff811681146200448a57600080fd5b8035600281106200448a57600080fd5b60008060008060008060008060006101008a8c031215620045f357600080fd5b620045fe8a6200447d565b98506200460e60208b01620045ae565b97506200461e60408b016200447d565b96506200462e60608b01620045c3565b95506200463e60808b016200447d565b945060a08a013567ffffffffffffffff808211156200465c57600080fd5b6200466a8d838e016200451c565b909650945060c08c01359150808211156200468457600080fd5b620046928d838e0162004292565b935060e08c0135915080821115620046a957600080fd5b50620046b88c828d0162004292565b9150509295985092959850929598565b600060208284031215620046db57600080fd5b5035919050565b600060208284031215620046f557600080fd5b813562002cc1816200445a565b80516200448a816200445a565b6000602082840312156200472257600080fd5b815162002cc1816200445a565b600082516200474381846020870162004339565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562002d905762002d906200474d565b8015158114620023e557600080fd5b600082601f830112620047b357600080fd5b8151620047c4620042b58262004249565b818152846020838601011115620047da57600080fd5b6200254682602083016020870162004339565b600080604083850312156200480157600080fd5b82516200480e8162004792565b602084015190925067ffffffffffffffff8111156200482c57600080fd5b6200432f85828601620047a1565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806200487e57607f821691505b602082108103620048b8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203620048f257620048f26200474d565b5060010190565b600081518084526020808501945080840160005b83811015620049d25781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a019190915261010091820151169088015261012090960195908201906001016200490d565b509495945050505050565b600081518084526020808501945080840160005b83811015620049d257815173ffffffffffffffffffffffffffffffffffffffff1687529582019590820190600101620049f1565b600081518084526020808501808196508360051b8101915082860160005b8581101562004a7157828403895262004a5e8483516200435f565b9885019893509084019060010162004a43565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a111562004abb57600080fd5b8960051b808c8386013783018381038201602085015262004adf8282018b620048f9565b915050828103604084015262004af68189620049dd565b9050828103606084015262004b0c8188620049dd565b9050828103608084015262004b22818762004a25565b905082810360a084015262004b38818662004a25565b905082810360c084015262004b4e818562004a25565b9b9a5050505050505050505050565b60006020828403121562004b7057600080fd5b815160ff8116811462002cc157600080fd5b60ff8416815260ff831660208201526060604082015260006200360d60608301846200435f565b60006020828403121562004bbc57600080fd5b815167ffffffffffffffff81111562004bd457600080fd5b6200254684828501620047a1565b60208152600062002d8d60208301846200435f565b600067ffffffffffffffff82111562004c145762004c1462004174565b5060051b60200190565b600082601f83011262004c3057600080fd5b8135602062004c43620042b58362004bf7565b82815260059290921b8401810191818101908684111562004c6357600080fd5b8286015b8481101562004c80578035835291830191830162004c67565b509695505050505050565b80356200448a8162004792565b80356fffffffffffffffffffffffffffffffff811681146200448a57600080fd5b80356bffffffffffffffffffffffff811681146200448a57600080fd5b600082601f83011262004ce857600080fd5b8135602062004cfb620042b58362004bf7565b828152610120928302850182019282820191908785111562004d1c57600080fd5b8387015b8581101562004df65781818a03121562004d3a5760008081fd5b62004d44620041a3565b62004d4f8262004c8b565b815262004d5e86830162004c8b565b86820152604062004d71818401620045ae565b90820152606062004d84838201620045ae565b90820152608062004d978382016200447d565b9082015260a062004daa83820162004c98565b9082015260c062004dbd83820162004cb9565b9082015260e062004dd0838201620045ae565b9082015261010062004de48382016200447d565b90820152845292840192810162004d20565b5090979650505050505050565b600082601f83011262004e1557600080fd5b8135602062004e28620042b58362004bf7565b82815260059290921b8401810191818101908684111562004e4857600080fd5b8286015b8481101562004c8057803562004e62816200445a565b835291830191830162004e4c565b600082601f83011262004e8257600080fd5b8135602062004e95620042b58362004bf7565b82815260059290921b8401810191818101908684111562004eb557600080fd5b8286015b8481101562004c8057803567ffffffffffffffff81111562004edb5760008081fd5b62004eeb8986838b010162004292565b84525091830191830162004eb9565b600080600080600080600060e0888a03121562004f1657600080fd5b873567ffffffffffffffff8082111562004f2f57600080fd5b62004f3d8b838c0162004c1e565b985060208a013591508082111562004f5457600080fd5b62004f628b838c0162004cd6565b975060408a013591508082111562004f7957600080fd5b62004f878b838c0162004e03565b965060608a013591508082111562004f9e57600080fd5b62004fac8b838c0162004e03565b955060808a013591508082111562004fc357600080fd5b62004fd18b838c0162004e70565b945060a08a013591508082111562004fe857600080fd5b62004ff68b838c0162004e70565b935060c08a01359150808211156200500d57600080fd5b506200501c8a828b0162004e70565b91505092959891949750929550565b600063ffffffff8083168181036200504757620050476200474d565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215620050b157600080fd5b5051919050565b8082018082111562002d905762002d906200474d565b6bffffffffffffffffffffffff8281168282160390808211156200388357620038836200474d565b805169ffffffffffffffffffff811681146200448a57600080fd5b600080600080600060a086880312156200512a57600080fd5b6200513586620050f6565b94506020860151935060408601519250606086015191506200515a60808701620050f6565b90509295509295909350565b60ff818116838216019081111562002d905762002d906200474d565b808202811582820484141762002d905762002d906200474d565b60008060408385031215620051b057600080fd5b505080516020909101519092909150565b6bffffffffffffffffffffffff8181168382160190808211156200388357620038836200474d565b60008154620051f88162004869565b808552602060018381168015620052185760018114620052515762005281565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b890101955062005281565b866000528260002060005b85811015620052795781548a82018601529083019084016200525c565b890184019650505b505050505092915050565b60208152600062002d8d6020830184620051e9565b600082601f830112620052b357600080fd5b81516020620052c6620042b58362004bf7565b82815260059290921b84018101918181019086841115620052e657600080fd5b8286015b8481101562004c805780518352918301918301620052ea565b6000602082840312156200531657600080fd5b815167ffffffffffffffff808211156200532f57600080fd5b9083019061010082860312156200534557600080fd5b6200534f620041d0565b82518152602083015160208201526040830151604082015260608301516060820152608083015160808201526200538960a0840162004702565b60a082015260c083015182811115620053a157600080fd5b620053af87828601620052a1565b60c08301525060e083015182811115620053c857600080fd5b620053d687828601620047a1565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015620049d257815187529582019590820190600101620053f9565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c08401516101008081850152506200548a610140840182620053e5565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084830301610120850152620054c882826200435f565b91505082810360208401526200360d8185620051e9565b601f82111562002e2557600081815260208120601f850160051c81016020861015620055085750805b601f850160051c820191505b81811015620055295782815560010162005514565b505050505050565b815167ffffffffffffffff8111156200554e576200554e62004174565b62005566816200555f845462004869565b84620054df565b602080601f831160018114620055bc5760008415620055855750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562005529565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156200560b57888601518255948401946001909101908401620055ea565b50858210156200564857878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b80516020808301519190811015620048b8577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600082620056d2577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000602082840312156200571957600080fd5b815162002cc1816200479256fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", + 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\":\"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\":[{\"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\":[],\"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\"}]", + Bin: "0x6101806040523480156200001257600080fd5b506040516200623b3803806200623b83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615b1a620007216000396000818160c4015261011a015260005050600061243e0152600081816119000152611c1901526000612572015260006137b301526000612656015260005050615b1a6000f3fe608060405260043610620000c25760003560e01c80638e86139b1162000073578063c80480221162000055578063c80480221462000261578063f2fde38b1462000286578063f7d334ba14620002ab57620000c2565b80638e86139b1462000208578063c62cf684146200022d57620000c2565b806379ba509711620000a957806379ba5097146200019e57806385c1b0ba14620001b65780638da5cb5b14620001db57620000c2565b8063349e8cca146200010a57806371791aa01462000164575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e80801562000103573d6000f35b3d6000fd5b005b3480156200011757600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156200017157600080fd5b5062000189620001833660046200430b565b620002d0565b6040516200015b9796959493929190620043f7565b348015620001ab57600080fd5b506200010862000a59565b348015620001c357600080fd5b5062000108620001d5366004620044ac565b62000b5c565b348015620001e857600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166200013a565b3480156200021557600080fd5b50620001086200022736600462004585565b620017c3565b3480156200023a57600080fd5b50620002526200024c366004620045f0565b62001b4b565b6040519081526020016200015b565b3480156200026e57600080fd5b506200010862000280366004620046e5565b62001ef8565b3480156200029357600080fd5b5062000108620002a5366004620046ff565b620023d0565b348015620002b857600080fd5b5062000189620002ca366004620046e5565b620023e8565b600060606000806000806000620002e662002426565b6000620002f38a62002498565b905060006014604051806101200160405290816000820160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a900462ffffff1662ffffff1662ffffff1681526020016000820160139054906101000a900461ffff1661ffff1661ffff1681526020016000820160159054906101000a900460ff1660ff1660ff1681526020016000820160169054906101000a900460ff161515151581526020016000820160179054906101000a900460ff161515151581526020016000820160189054906101000a900460ff161515151581526020016001820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000600460008d8152602001908152602001600020604051806101200160405290816000820160009054906101000a900460ff161515151581526020016000820160019054906101000a900460ff161515151581526020016000820160029054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160069054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600a9054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016001820160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020016001820160109054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff166bffffffffffffffffffffffff16815260200160018201601c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152505090506000808360a0015115620006b85750506040805160208101825260008082529290910151919a5098506009975089965063ffffffff16945085935083925062000a4d915050565b606083015163ffffffff90811614620007045750506040805160208101825260008082529290910151919a5098506001975089965063ffffffff16945085935083925062000a4d915050565b825115620007455750506040805160208101825260008082529290910151919a5098506002975089965063ffffffff16945085935083925062000a4d915050565b62000750846200254e565b809450819850829950505050620007778e858786604001518b8b888a610100015162002756565b9050806bffffffffffffffffffffffff168360c001516bffffffffffffffffffffffff161015620007db5750506040805160208101825260008082529290910151919a5098506006975089965063ffffffff16945085935083925062000a4d915050565b50506000620007ec8d858e62002af4565b90505a9750600080836080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000844573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200086a91906200472c565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff1684604051620008ac91906200474c565b60006040518083038160008787f1925050503d8060008114620008ec576040519150601f19603f3d011682016040523d82523d6000602084013e620008f1565b606091505b50915091505a62000903908b62004799565b9950816200098d576018548151780100000000000000000000000000000000000000000000000090910463ffffffff1610156200096b5750506040805160208101825260008082529390910151929b509950600898505063ffffffff16945062000a4d915050565b604090930151929a50600399505063ffffffff909116955062000a4d92505050565b80806020019051810190620009a391906200480a565b909d509b508c620009df5750506040805160208101825260008082529390910151929b509950600498505063ffffffff16945062000a4d915050565b6018548c517401000000000000000000000000000000000000000090910463ffffffff16101562000a3b5750506040805160208101825260008082529390910151929b509950600598505063ffffffff16945062000a4d915050565b5050506040015163ffffffff16945050505b92959891949750929550565b60015473ffffffffffffffffffffffffffffffffffffffff16331462000ae0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b600173ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000b9b5762000b9b620043c8565b1415801562000be75750600373ffffffffffffffffffffffffffffffffffffffff82166000908152601c602052604090205460ff16600381111562000be45762000be4620043c8565b14155b1562000c1f576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60165473ffffffffffffffffffffffffffffffffffffffff1662000c6f576040517fd12d7d8d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082900362000cab576040517f2c2fc94100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805161012081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905260008467ffffffffffffffff81111562000d115762000d1162004191565b60405190808252806020026020018201604052801562000d3b578160200160208202803683370190505b50905060008567ffffffffffffffff81111562000d5c5762000d5c62004191565b60405190808252806020026020018201604052801562000df357816020015b604080516101208101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c0820181905260e0820181905261010082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018162000d7b5790505b50905060008667ffffffffffffffff81111562000e145762000e1462004191565b60405190808252806020026020018201604052801562000e4957816020015b606081526020019060019003908162000e335790505b50905060008767ffffffffffffffff81111562000e6a5762000e6a62004191565b60405190808252806020026020018201604052801562000e9f57816020015b606081526020019060019003908162000e895790505b50905060008867ffffffffffffffff81111562000ec05762000ec062004191565b60405190808252806020026020018201604052801562000ef557816020015b606081526020019060019003908162000edf5790505b50905060005b898110156200159b578a8a8281811062000f195762000f1962004857565b60209081029290920135600081815260048452604090819020815161012081018352815460ff8082161515835261010080830490911615159783019790975263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e08201526002909101549091169381019390935299509097506200103690508862002ce4565b60808701516040517f1a5da6c800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015290911690631a5da6c890602401600060405180830381600087803b158015620010a657600080fd5b505af1158015620010bb573d6000803e3d6000fd5b5050505086858281518110620010d557620010d562004857565b60200260200101819052506005600089815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1686828151811062001129576200112962004857565b73ffffffffffffffffffffffffffffffffffffffff90921660209283029190910182015260008981526007909152604090208054620011689062004886565b80601f0160208091040260200160405190810160405280929190818152602001828054620011969062004886565b8015620011e75780601f10620011bb57610100808354040283529160200191620011e7565b820191906000526020600020905b815481529060010190602001808311620011c957829003601f168201915b505050505084828151811062001201576200120162004857565b6020026020010181905250601d600089815260200190815260200160002080546200122c9062004886565b80601f01602080910402602001604051908101604052809291908181526020018280546200125a9062004886565b8015620012ab5780601f106200127f57610100808354040283529160200191620012ab565b820191906000526020600020905b8154815290600101906020018083116200128d57829003601f168201915b5050505050838281518110620012c557620012c562004857565b6020026020010181905250601e60008981526020019081526020016000208054620012f09062004886565b80601f01602080910402602001604051908101604052809291908181526020018280546200131e9062004886565b80156200136f5780601f1062001343576101008083540402835291602001916200136f565b820191906000526020600020905b8154815290600101906020018083116200135157829003601f168201915b505050505082828151811062001389576200138962004857565b602090810291909101810191909152600089815260048252604080822080547fffff0000000000000000000000000000000000000000000000000000000000001681556001810183905560020180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560079092529081206200140f916200412d565b6000888152601d6020526040812062001428916200412d565b6000888152601e6020526040812062001441916200412d565b600088815260066020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556200148260028962002d9b565b5060c0870151604080516bffffffffffffffffffffffff909216825273ffffffffffffffffffffffffffffffffffffffff8b16602083015289917fb38647142fbb1ea4c000fc4569b37a4e9a9f6313317b84ee3e5326c1a6cd06ff910160405180910390a260c087015161010088015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604090205462001531916bffffffffffffffffffffffff169062004799565b6101008801805173ffffffffffffffffffffffffffffffffffffffff90811660009081526021602052604090209290925560c08901519051620015869216908b906bffffffffffffffffffffffff1662002db2565b806200159281620048db565b91505062000efb565b5060008a8a868167ffffffffffffffff811115620015bd57620015bd62004191565b604051908082528060200260200182016040528015620015e7578160200160208202803683370190505b50898888886040516020016200160598979695949392919062004a9b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282526016547faab9edd6000000000000000000000000000000000000000000000000000000008452915190935073ffffffffffffffffffffffffffffffffffffffff808d1693638e86139b939091169163c71249ab91600391869163aab9edd69160048083019260209291908290030181865afa158015620016b7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620016dd919062004b7a565b866040518463ffffffff1660e01b8152600401620016fe9392919062004b9f565b600060405180830381865afa1580156200171c573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405262001764919081019062004bc6565b6040518263ffffffff1660e01b815260040162001782919062004bff565b600060405180830381600087803b1580156200179d57600080fd5b505af1158015620017b2573d6000803e3d6000fd5b505050505050505050505050505050565b6002336000908152601c602052604090205460ff166003811115620017ec57620017ec620043c8565b141580156200182257506003336000908152601c602052604090205460ff1660038111156200181f576200181f620043c8565b14155b156200185a576040517f0ebeec3c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080808080808062001870888a018a62004f17565b965096509650965096509650965060005b875181101562001b3f57600073ffffffffffffffffffffffffffffffffffffffff16878281518110620018b857620018b862004857565b60200260200101516080015173ffffffffffffffffffffffffffffffffffffffff1603620019cc57858181518110620018f557620018f562004857565b6020026020010151307f00000000000000000000000000000000000000000000000000000000000000006040516200192d906200416c565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001977573d6000803e3d6000fd5b508782815181106200198d576200198d62004857565b60200260200101516080019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff16815250505b62001a84888281518110620019e557620019e562004857565b602002602001015188838151811062001a025762001a0262004857565b602002602001015187848151811062001a1f5762001a1f62004857565b602002602001015187858151811062001a3c5762001a3c62004857565b602002602001015187868151811062001a595762001a5962004857565b602002602001015187878151811062001a765762001a7662004857565b602002602001015162002e46565b87818151811062001a995762001a9962004857565b60200260200101517f74931a144e43a50694897f241d973aecb5024c0e910f9bb80a163ea3c1cf5a7188838151811062001ad75762001ad762004857565b602002602001015160c001513360405162001b229291906bffffffffffffffffffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a28062001b3681620048db565b91505062001881565b50505050505050505050565b6000805473ffffffffffffffffffffffffffffffffffffffff16331480159062001b7f575062001b7d60093362003363565b155b1562001bb7576040517fd48b678b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8a163b62001c06576040517f09ee12d500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b62001c118762003393565b905060008a307f000000000000000000000000000000000000000000000000000000000000000060405162001c46906200416c565b73ffffffffffffffffffffffffffffffffffffffff938416815291831660208301529091166040820152606001604051809103906000f08015801562001c90573d6000803e3d6000fd5b50905062001d81826040518061012001604052806000151581526020016000151581526020018d63ffffffff16815260200163ffffffff801681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff168152602001600063ffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152508b89898080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508b92508a915062002e469050565b601680547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690601c62001db98362005048565b91906101000a81548163ffffffff021916908363ffffffff16021790555050817fbae366358c023f887e791d7a62f2e4316f1026bd77f6fb49501a917b3bc5d0128b8b60405162001e3292919063ffffffff92909216825273ffffffffffffffffffffffffffffffffffffffff16602082015260400190565b60405180910390a2817fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d878760405162001e6e9291906200506e565b60405180910390a2817f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d56648560405162001ea8919062004bff565b60405180910390a2817f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf48508460405162001ee2919062004bff565b60405180910390a2509998505050505050505050565b6000818152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e082015260029091015490911691810191909152906200201c60005473ffffffffffffffffffffffffffffffffffffffff1690565b61010083015173ffffffffffffffffffffffffffffffffffffffff90811660009081526022602090815260408083206002015460155482517f57e871e70000000000000000000000000000000000000000000000000000000081529251968616331497506bffffffffffffffffffffffff90911695939416926357e871e7926004808401939192918290030181865afa158015620020be573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620020e49190620050bb565b9050836060015163ffffffff166000036200212b576040517ffbc0357800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b606084015163ffffffff9081161462002170576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82158015620021a3575060008581526005602052604090205473ffffffffffffffffffffffffffffffffffffffff163314155b15620021db576040517ffbdb8e5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82620021f157620021ee603282620050d5565b90505b6000858152600460205260409020805463ffffffff8084166601000000000000027fffffffffffffffffffffffffffffffffffffffffffff00000000ffffffffffff909216919091179091556200224e90600290879062002d9b16565b506000826bffffffffffffffffffffffff168560a001516fffffffffffffffffffffffffffffffff161015620022c15760a08501516200228f9084620050eb565b90508460c001516bffffffffffffffffffffffff16816bffffffffffffffffffffffff161115620022c1575060c08401515b808560c00151620022d39190620050eb565b600087815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010089015173ffffffffffffffffffffffffffffffffffffffff1683526021909152902054620023659183169062004799565b61010086015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604080822092909255905167ffffffffffffffff84169188917f91cb3bb75cfbd718bbfccc56b7f53d92d7048ef4ca39a3b7b7c6d4af1f7911819190a3505050505050565b620023da62003632565b620023e581620036b5565b50565b6000606060008060008060006200240f8860405180602001604052806000815250620002d0565b959e949d50929b5090995097509550909350915050565b3273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161462002496576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b6000818160045b600f8110156200252d577fff000000000000000000000000000000000000000000000000000000000000008216838260208110620024e157620024e162004857565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146200251857506000949350505050565b806200252481620048db565b9150506200249f565b5081600f1a6001811115620025465762002546620043c8565b949350505050565b600080600080846040015162ffffff1690506000808263ffffffff161190506000807f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015620025dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200260291906200512e565b50945090925050506000811315806200261a57508142105b806200263f57508280156200263f575062002636824262004799565b8463ffffffff16105b156200265057601954965062002654565b8096505b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015620026c0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620026e691906200512e565b5094509092505050600081131580620026fe57508142105b806200272357508280156200272357506200271a824262004799565b8463ffffffff16105b156200273457601a54955062002738565b8095505b8686620027458a620037ac565b965096509650505050509193909250565b6000808080896001811115620027705762002770620043c8565b0362002780575061ea60620027da565b6001896001811115620027975762002797620043c8565b03620027a8575062014c08620027da565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008a608001516001620027ef919062005183565b620027ff9060ff1660406200519f565b6018546200282f906103a49074010000000000000000000000000000000000000000900463ffffffff16620050d5565b6200283b9190620050d5565b601554604080517fde9ee35e0000000000000000000000000000000000000000000000000000000081528151939450600093849373ffffffffffffffffffffffffffffffffffffffff169263de9ee35e92600480820193918290030181865afa158015620028ad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620028d39190620051b9565b90925090508183620028e7836018620050d5565b620028f391906200519f565b60808f01516200290590600162005183565b620029169060ff166115e06200519f565b620029229190620050d5565b6200292e9190620050d5565b6200293a9085620050d5565b6101008e01516040517f125441400000000000000000000000000000000000000000000000000000000081526004810186905291955073ffffffffffffffffffffffffffffffffffffffff1690631254414090602401602060405180830381865afa158015620029ae573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620029d49190620050bb565b8d6060015161ffff16620029e991906200519f565b94505050506000620029fc8b86620038a6565b60008d815260046020526040902054909150610100900460ff161562002a625760008c81526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845284529151909116908201525b600062002ace8c6040518061012001604052808d63ffffffff1681526020018681526020018781526020018c81526020018b81526020018a81526020018973ffffffffffffffffffffffffffffffffffffffff1681526020018581526020016000151581525062003a01565b6020810151815191925062002ae391620051de565b9d9c50505050505050505050505050565b6060600083600181111562002b0d5762002b0d620043c8565b0362002bda576000848152600760205260409081902090517f6e04ff0d000000000000000000000000000000000000000000000000000000009162002b5591602401620052a9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152905062002cdd565b600183600181111562002bf15762002bf1620043c8565b03620027a85760008280602001905181019062002c0f919062005320565b6000868152600760205260409081902090519192507f40691db4000000000000000000000000000000000000000000000000000000009162002c5691849160240162005434565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152915062002cdd9050565b9392505050565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331462002d42576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614620023e5576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600062002da9838362003bf8565b90505b92915050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905262002e4190849062003cfc565b505050565b601454760100000000000000000000000000000000000000000000900460ff161562002e9e576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60175483517c010000000000000000000000000000000000000000000000000000000090910463ffffffff16101562002f03576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6108fc856040015163ffffffff16108062002f495750601654604086015163ffffffff780100000000000000000000000000000000000000000000000090920482169116115b1562002f81576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000868152600460205260409020546a0100000000000000000000900473ffffffffffffffffffffffffffffffffffffffff161562002fec576040517f6e3b930b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61010085015173ffffffffffffffffffffffffffffffffffffffff9081166000908152602260205260409020546701000000000000009004166200305c576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b846004600088815260200190815260200160002060008201518160000160006101000a81548160ff02191690831515021790555060208201518160000160016101000a81548160ff02191690831515021790555060408201518160000160026101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160066101000a81548163ffffffff021916908363ffffffff160217905550608082015181600001600a6101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555060c08201518160010160106101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050836005600088815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555082600760008881526020019081526020016000209081620032a191906200554e565b5060c085015161010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040902054620032ec916bffffffffffffffffffffffff1690620050d5565b61010086015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020908152604080832093909355888252601d9052206200333183826200554e565b506000868152601e602052604090206200334c82826200554e565b506200335a60028762003e0f565b50505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600183016020526040812054151562002da9565b601554604080517f57e871e70000000000000000000000000000000000000000000000000000000081529051600092839273ffffffffffffffffffffffffffffffffffffffff90911691839183916385df51fd9160019184916357e871e79160048083019260209291908290030181865afa15801562003417573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200343d9190620050bb565b62003449919062004799565b6040518263ffffffff1660e01b81526004016200346891815260200190565b602060405180830381865afa15801562003486573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620034ac9190620050bb565b60165460408051602081019390935230908301527c0100000000000000000000000000000000000000000000000000000000900463ffffffff166060820152608001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201209083015201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152919052905060045b600f811015620035c057838282815181106200357c576200357c62004857565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080620035b781620048db565b9150506200355c565b50846001811115620035d657620035d6620043c8565b60f81b81600f81518110620035ef57620035ef62004857565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350620036298162005675565b95945050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331462002496576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640162000ad7565b3373ffffffffffffffffffffffffffffffffffffffff82160362003736576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000ad7565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa1580156200381d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200384391906200512e565b509350509250506000821315806200385a57508042105b806200388e57506000846040015162ffffff161180156200388e575062003882814262004799565b846040015162ffffff16105b156200389f575050601b5492915050565b5092915050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa15801562003969573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200398f91906200512e565b50935050925050600082131580620039a657508042105b80620039da57506000866040015162ffffff16118015620039da5750620039ce814262004799565b866040015162ffffff16105b15620039f05760018301546040850152620039f8565b604084018290525b50505092915050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff16836060015162003a4191906200519f565b9050826101000151801562003a555750803a105b1562003a5e57503a5b60008360a0015184604001518560200151866000015162003a809190620050d5565b62003a8c90856200519f565b62003a989190620050d5565b62003aa491906200519f565b905062003ac68460e00151604001518262003ac09190620056b8565b62003e1d565b6bffffffffffffffffffffffff168352608084015162003aec9062003ac09083620056b8565b6bffffffffffffffffffffffff16604084015260e08401516020015160009062003b259062ffffff16683635c9adc5dea000006200519f565b9050600081633b9aca008760a001518860e001516000015163ffffffff1689604001518a600001518962003b5a91906200519f565b62003b669190620050d5565b62003b7291906200519f565b62003b7e91906200519f565b62003b8a9190620056b8565b62003b969190620050d5565b905062003bb28660e00151604001518262003ac09190620056b8565b6bffffffffffffffffffffffff166020860152608086015162003bdb9062003ac09083620056b8565b6bffffffffffffffffffffffff1660608601525050505092915050565b6000818152600183016020526040812054801562003cf157600062003c1f60018362004799565b855490915060009062003c359060019062004799565b905081811462003ca157600086600001828154811062003c595762003c5962004857565b906000526020600020015490508087600001848154811062003c7f5762003c7f62004857565b6000918252602080832090910192909255918252600188019052604090208390555b855486908062003cb55762003cb5620056f4565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505062002dac565b600091505062002dac565b600062003d60826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1662003ec19092919063ffffffff16565b80519091501562002e41578080602001905181019062003d81919062005723565b62002e41576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f74207375636365656400000000000000000000000000000000000000000000606482015260840162000ad7565b600062002da9838362003ed2565b60006bffffffffffffffffffffffff82111562003ebd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f3620626974730000000000000000000000000000000000000000000000000000606482015260840162000ad7565b5090565b606062002546848460008562003f24565b600081815260018301602052604081205462003f1b5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562002dac565b50600062002dac565b60608247101562003fb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c0000000000000000000000000000000000000000000000000000606482015260840162000ad7565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405162003fe391906200474c565b60006040518083038185875af1925050503d806000811462004022576040519150601f19603f3d011682016040523d82523d6000602084013e62004027565b606091505b50915091506200403a8783838762004045565b979650505050505050565b60608315620040e0578251600003620040d85773ffffffffffffffffffffffffffffffffffffffff85163b620040d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640162000ad7565b508162002546565b620025468383815115620040f75781518083602001fd5b806040517f08c379a000000000000000000000000000000000000000000000000000000000815260040162000ad7919062004bff565b5080546200413b9062004886565b6000825580601f106200414c575050565b601f016020900490600052602060002090810190620023e591906200417a565b6103ca806200574483390190565b5b8082111562003ebd57600081556001016200417b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610120810167ffffffffffffffff81118282101715620041e757620041e762004191565b60405290565b604051610100810167ffffffffffffffff81118282101715620041e757620041e762004191565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156200425e576200425e62004191565b604052919050565b600067ffffffffffffffff82111562004283576200428362004191565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112620042c157600080fd5b8135620042d8620042d28262004266565b62004214565b818152846020838601011115620042ee57600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156200431f57600080fd5b82359150602083013567ffffffffffffffff8111156200433e57600080fd5b6200434c85828601620042af565b9150509250929050565b60005b838110156200437357818101518382015260200162004359565b50506000910152565b600081518084526200439681602086016020860162004356565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b871515815260e0602082015260006200441460e08301896200437c565b9050600a87106200444e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201969096526060810194909452608084019290925260a083015260c09091015292915050565b73ffffffffffffffffffffffffffffffffffffffff81168114620023e557600080fd5b8035620044a78162004477565b919050565b600080600060408486031215620044c257600080fd5b833567ffffffffffffffff80821115620044db57600080fd5b818601915086601f830112620044f057600080fd5b8135818111156200450057600080fd5b8760208260051b85010111156200451657600080fd5b602092830195509350508401356200452e8162004477565b809150509250925092565b60008083601f8401126200454c57600080fd5b50813567ffffffffffffffff8111156200456557600080fd5b6020830191508360208285010111156200457e57600080fd5b9250929050565b600080602083850312156200459957600080fd5b823567ffffffffffffffff811115620045b157600080fd5b620045bf8582860162004539565b90969095509350505050565b803563ffffffff81168114620044a757600080fd5b803560028110620044a757600080fd5b60008060008060008060008060006101008a8c0312156200461057600080fd5b6200461b8a6200449a565b98506200462b60208b01620045cb565b97506200463b60408b016200449a565b96506200464b60608b01620045e0565b95506200465b60808b016200449a565b945060a08a013567ffffffffffffffff808211156200467957600080fd5b620046878d838e0162004539565b909650945060c08c0135915080821115620046a157600080fd5b620046af8d838e01620042af565b935060e08c0135915080821115620046c657600080fd5b50620046d58c828d01620042af565b9150509295985092959850929598565b600060208284031215620046f857600080fd5b5035919050565b6000602082840312156200471257600080fd5b813562002cdd8162004477565b8051620044a78162004477565b6000602082840312156200473f57600080fd5b815162002cdd8162004477565b600082516200476081846020870162004356565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8181038181111562002dac5762002dac6200476a565b8015158114620023e557600080fd5b600082601f830112620047d057600080fd5b8151620047e1620042d28262004266565b818152846020838601011115620047f757600080fd5b6200254682602083016020870162004356565b600080604083850312156200481e57600080fd5b82516200482b81620047af565b602084015190925067ffffffffffffffff8111156200484957600080fd5b6200434c85828601620047be565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600181811c908216806200489b57607f821691505b602082108103620048d5577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200490f576200490f6200476a565b5060010190565b600081518084526020808501945080840160005b83811015620049ef5781518051151588528381015115158489015260408082015163ffffffff908116918a01919091526060808301518216908a015260808083015173ffffffffffffffffffffffffffffffffffffffff908116918b019190915260a0808401516fffffffffffffffffffffffffffffffff16908b015260c0808401516bffffffffffffffffffffffff16908b015260e080840151909216918a019190915261010091820151169088015261012090960195908201906001016200492a565b509495945050505050565b600081518084526020808501945080840160005b83811015620049ef57815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010162004a0e565b600081518084526020808501808196508360051b8101915082860160005b8581101562004a8e57828403895262004a7b8483516200437c565b9885019893509084019060010162004a60565b5091979650505050505050565b60e081528760e082015260006101007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a111562004ad857600080fd5b8960051b808c8386013783018381038201602085015262004afc8282018b62004916565b915050828103604084015262004b138189620049fa565b9050828103606084015262004b298188620049fa565b9050828103608084015262004b3f818762004a42565b905082810360a084015262004b55818662004a42565b905082810360c084015262004b6b818562004a42565b9b9a5050505050505050505050565b60006020828403121562004b8d57600080fd5b815160ff8116811462002cdd57600080fd5b60ff8416815260ff831660208201526060604082015260006200362960608301846200437c565b60006020828403121562004bd957600080fd5b815167ffffffffffffffff81111562004bf157600080fd5b6200254684828501620047be565b60208152600062002da960208301846200437c565b600067ffffffffffffffff82111562004c315762004c3162004191565b5060051b60200190565b600082601f83011262004c4d57600080fd5b8135602062004c60620042d28362004c14565b82815260059290921b8401810191818101908684111562004c8057600080fd5b8286015b8481101562004c9d578035835291830191830162004c84565b509695505050505050565b8035620044a781620047af565b80356fffffffffffffffffffffffffffffffff81168114620044a757600080fd5b80356bffffffffffffffffffffffff81168114620044a757600080fd5b600082601f83011262004d0557600080fd5b8135602062004d18620042d28362004c14565b828152610120928302850182019282820191908785111562004d3957600080fd5b8387015b8581101562004e135781818a03121562004d575760008081fd5b62004d61620041c0565b62004d6c8262004ca8565b815262004d7b86830162004ca8565b86820152604062004d8e818401620045cb565b90820152606062004da1838201620045cb565b90820152608062004db48382016200449a565b9082015260a062004dc783820162004cb5565b9082015260c062004dda83820162004cd6565b9082015260e062004ded838201620045cb565b9082015261010062004e018382016200449a565b90820152845292840192810162004d3d565b5090979650505050505050565b600082601f83011262004e3257600080fd5b8135602062004e45620042d28362004c14565b82815260059290921b8401810191818101908684111562004e6557600080fd5b8286015b8481101562004c9d57803562004e7f8162004477565b835291830191830162004e69565b600082601f83011262004e9f57600080fd5b8135602062004eb2620042d28362004c14565b82815260059290921b8401810191818101908684111562004ed257600080fd5b8286015b8481101562004c9d57803567ffffffffffffffff81111562004ef85760008081fd5b62004f088986838b0101620042af565b84525091830191830162004ed6565b600080600080600080600060e0888a03121562004f3357600080fd5b873567ffffffffffffffff8082111562004f4c57600080fd5b62004f5a8b838c0162004c3b565b985060208a013591508082111562004f7157600080fd5b62004f7f8b838c0162004cf3565b975060408a013591508082111562004f9657600080fd5b62004fa48b838c0162004e20565b965060608a013591508082111562004fbb57600080fd5b62004fc98b838c0162004e20565b955060808a013591508082111562004fe057600080fd5b62004fee8b838c0162004e8d565b945060a08a01359150808211156200500557600080fd5b620050138b838c0162004e8d565b935060c08a01359150808211156200502a57600080fd5b50620050398a828b0162004e8d565b91505092959891949750929550565b600063ffffffff8083168181036200506457620050646200476a565b6001019392505050565b60208152816020820152818360408301376000818301604090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101919050565b600060208284031215620050ce57600080fd5b5051919050565b8082018082111562002dac5762002dac6200476a565b6bffffffffffffffffffffffff8281168282160390808211156200389f576200389f6200476a565b805169ffffffffffffffffffff81168114620044a757600080fd5b600080600080600060a086880312156200514757600080fd5b620051528662005113565b9450602086015193506040860151925060608601519150620051776080870162005113565b90509295509295909350565b60ff818116838216019081111562002dac5762002dac6200476a565b808202811582820484141762002dac5762002dac6200476a565b60008060408385031215620051cd57600080fd5b505080516020909101519092909150565b6bffffffffffffffffffffffff8181168382160190808211156200389f576200389f6200476a565b60008154620052158162004886565b8085526020600183811680156200523557600181146200526e576200529e565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008516838901528284151560051b89010195506200529e565b866000528260002060005b85811015620052965781548a820186015290830190840162005279565b890184019650505b505050505092915050565b60208152600062002da9602083018462005206565b600082601f830112620052d057600080fd5b81516020620052e3620042d28362004c14565b82815260059290921b840181019181810190868411156200530357600080fd5b8286015b8481101562004c9d578051835291830191830162005307565b6000602082840312156200533357600080fd5b815167ffffffffffffffff808211156200534c57600080fd5b9083019061010082860312156200536257600080fd5b6200536c620041ed565b8251815260208301516020820152604083015160408201526060830151606082015260808301516080820152620053a660a084016200471f565b60a082015260c083015182811115620053be57600080fd5b620053cc87828601620052be565b60c08301525060e083015182811115620053e557600080fd5b620053f387828601620047be565b60e08301525095945050505050565b600081518084526020808501945080840160005b83811015620049ef5781518752958201959082019060010162005416565b60408152825160408201526020830151606082015260408301516080820152606083015160a0820152608083015160c082015273ffffffffffffffffffffffffffffffffffffffff60a08401511660e0820152600060c0840151610100808185015250620054a761014084018262005402565b905060e08501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc084830301610120850152620054e582826200437c565b915050828103602084015262003629818562005206565b601f82111562002e4157600081815260208120601f850160051c81016020861015620055255750805b601f850160051c820191505b81811015620055465782815560010162005531565b505050505050565b815167ffffffffffffffff8111156200556b576200556b62004191565b62005583816200557c845462004886565b84620054fc565b602080601f831160018114620055d95760008415620055a25750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855562005546565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b82811015620056285788860151825594840194600190910190840162005607565b50858210156200566557878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b01905550565b80516020808301519190811015620048d5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60209190910360031b1b16919050565b600082620056ef577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000602082840312156200573657600080fd5b815162002cdd81620047af56fe60c060405234801561001057600080fd5b506040516103ca3803806103ca83398101604081905261002f91610076565b600080546001600160a01b0319166001600160a01b039384161790559181166080521660a0526100b9565b80516001600160a01b038116811461007157600080fd5b919050565b60008060006060848603121561008b57600080fd5b6100948461005a565b92506100a26020850161005a565b91506100b06040850161005a565b90509250925092565b60805160a0516102e76100e36000396000603801526000818160c4015261011701526102e76000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806379188d161461007b578063f00e6a2a146100aa575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610076573d6000f35b3d6000fd5b61008e6100893660046101c1565b6100ee565b6040805192151583526020830191909152015b60405180910390f35b60405173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001681526020016100a1565b60008054819073ffffffffffffffffffffffffffffffffffffffff16331461011557600080fd5b7f00000000000000000000000000000000000000000000000000000000000000005a91505a61138881101561014957600080fd5b61138881039050856040820482031161016157600080fd5b50803b61016d57600080fd5b6000808551602087016000858af192505a610188908361029a565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080604083850312156101d457600080fd5b82359150602083013567ffffffffffffffff808211156101f357600080fd5b818501915085601f83011261020757600080fd5b81358181111561021957610219610192565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561025f5761025f610192565b8160405282815288602084870101111561027857600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b818103818111156102d4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9291505056fea164736f6c6343000813000aa164736f6c6343000813000a", } var AutomationRegistryLogicAABI = AutomationRegistryLogicAMetaData.ABI @@ -1280,42 +1280,42 @@ func (it *AutomationRegistryLogicAFeesWithdrawnIterator) Close() error { } type AutomationRegistryLogicAFeesWithdrawn struct { - Recipient common.Address AssetAddress common.Address + Recipient common.Address Amount *big.Int Raw types.Log } -func (_AutomationRegistryLogicA *AutomationRegistryLogicAFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryLogicAFeesWithdrawnIterator, error) { +func (_AutomationRegistryLogicA *AutomationRegistryLogicAFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicAFeesWithdrawnIterator, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistryLogicA.contract.FilterLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistryLogicA.contract.FilterLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } return &AutomationRegistryLogicAFeesWithdrawnIterator{contract: _AutomationRegistryLogicA.contract, event: "FeesWithdrawn", logs: logs, sub: sub}, nil } -func (_AutomationRegistryLogicA *AutomationRegistryLogicAFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicAFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) { +func (_AutomationRegistryLogicA *AutomationRegistryLogicAFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicAFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistryLogicA.contract.WatchLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistryLogicA.contract.WatchLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } @@ -5324,9 +5324,9 @@ type AutomationRegistryLogicAInterface interface { ParseDedupKeyAdded(log types.Log) (*AutomationRegistryLogicADedupKeyAdded, error) - FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryLogicAFeesWithdrawnIterator, error) + FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicAFeesWithdrawnIterator, error) - WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicAFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) + WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicAFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) ParseFeesWithdrawn(log types.Log) (*AutomationRegistryLogicAFeesWithdrawn, error) 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 f74224af9f4..160c5222c95 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 @@ -44,8 +44,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\":\"int256\",\"name\":\"available\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"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\":\"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\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"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\":\"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\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"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\":\"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\":\"address\",\"name\":\"assetAddress\",\"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\":\"withdrawLinkFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x6101806040523480156200001257600080fd5b5060405162003bd538038062003bd583398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e051610100516101205161014051610160516134ab6200072a6000396000818161016c0152610219015260008181611700015261195c015260006121620152600050506000505060005050600050506000818161127d015281816113270152611fb401526134ab6000f3fe60806040526004361061016a5760003560e01c80638765ecbe116100cb578063a86e17811161007f578063ce7dc5b411610059578063ce7dc5b414610431578063d09dc33914610451578063f2fde38b146104745761016a565b8063a86e1781146103d1578063b148ab6b146103f1578063cd7f71b5146104115761016a565b80638dcf0fe7116100b05780638dcf0fe71461037e578063948108f71461039e578063a72aa27e146103b15761016a565b80638765ecbe146103335780638da5cb5b146103535761016a565b806368d369d811610122578063744bfe6111610107578063744bfe61146102de57806379ba5097146102fe5780638081fadb146103135761016a565b806368d369d81461029e57806371fae17f146102be5761016a565b8063349e8cca11610153578063349e8cca1461020a5780634ee88d351461025e5780635165f2f51461027e5761016a565b80631a2af011146101b157806329c5efad146101d1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101aa573d6000f35b3d6000fd5b005b3480156101bd57600080fd5b506101af6101cc3660046129ae565b610494565b3480156101dd57600080fd5b506101f16101ec366004612af8565b61059a565b6040516102019493929190612bad565b60405180910390f35b34801561021657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610201565b34801561026a57600080fd5b506101af610279366004612c5c565b610878565b34801561028a57600080fd5b506101af610299366004612ca8565b6108da565b3480156102aa57600080fd5b506101af6102b9366004612cc1565b610a8c565b3480156102ca57600080fd5b506101af6102d9366004612ca8565b610b6e565b3480156102ea57600080fd5b506101af6102f93660046129ae565b610c04565b34801561030a57600080fd5b506101af61107c565b34801561031f57600080fd5b506101af61032e366004612d02565b61117e565b34801561033f57600080fd5b506101af61034e366004612ca8565b6113b2565b34801561035f57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610239565b34801561038a57600080fd5b506101af610399366004612c5c565b611567565b6101af6103ac366004612d2e565b6115bc565b3480156103bd57600080fd5b506101af6103cc366004612d76565b611a2c565b3480156103dd57600080fd5b506101af6103ec366004612d9b565b611b2b565b3480156103fd57600080fd5b506101af61040c366004612ca8565b611c0c565b34801561041d57600080fd5b506101af61042c366004612c5c565b611e39565b34801561043d57600080fd5b506101f161044c366004612df1565b611ef0565b34801561045d57600080fd5b50610466611fb2565b604051908152602001610201565b34801561048057600080fd5b506101af61048f366004612ee5565b612081565b61049d82612095565b3373ffffffffffffffffffffffffffffffffffffffff8216036104ec576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146105965760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b600060606000806105a961214a565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107239190612f09565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff16896040516107639190612f26565b60006040518083038160008787f1925050503d80600081146107a1576040519150601f19603f3d011682016040523d82523d6000602084013e6107a6565b606091505b50915091505a6107b69085612f71565b9350816107df57600060405180602001604052806000815250600796509650965050505061086f565b808060200190518101906107f39190612f99565b90975095508661081f57600060405180602001604052806000815250600496509650965050505061086f565b60185486517401000000000000000000000000000000000000000090910463ffffffff16101561086b57600060405180602001604052806000815250600596509650965050505061086f565b5050505b92959194509250565b61088183612095565b6000838152601d6020526040902061089a8284836130c4565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d566483836040516108cd929190613228565b60405180910390a2505050565b6108e381612095565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a1d576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610a5c6002836121bb565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610a946121d0565b73ffffffffffffffffffffffffffffffffffffffff8216610ae1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610b0273ffffffffffffffffffffffffffffffffffffffff84168383612221565b8273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa883604051610b6191815260200190565b60405180910390a3505050565b610b766122b3565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff1615610c5c576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff8116610ceb576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314610e2b576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015610e9b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ebf919061323c565b816060015163ffffffff161115610f02576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff1690610f6d908290612f71565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff16905551610ff09116846bffffffffffffffffffffffff8416612221565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611102576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6111866121d0565b73ffffffffffffffffffffffffffffffffffffffff82166111d3576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006111dd611fb2565b905060008112806111ed57508082115b1561122e576040517fd1e2061400000000000000000000000000000000000000000000000000000000815260048101829052602481018390526044016110f9565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af11580156112c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ec9190613255565b905080611325576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa8856040516113a491815260200190565b60405180910390a350505050565b6113bb81612095565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e0830152600290920154909316908301526114f5576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055611537600283612304565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b61157083612095565b6000838152601e602052604090206115898284836130c4565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf485083836040516108cd929190613228565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e084015260029093015416928101929092529091146116f8576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415611794577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff1614611788576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61179134612310565b91505b818160c001516117a49190613270565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff168352602190915290205461183491841690613295565b61010082015173ffffffffffffffffffffffffffffffffffffffff1660009081526021602052604081209190915534900361195a576101008101516040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526bffffffffffffffffffffffff8416604482015260009173ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303816000875af11580156118f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061191b9190613255565b905080611954576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b506119ea565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b1580156119d057600080fd5b505af11580156119e4573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa73489150620390602001610b61565b6108fc8163ffffffff161080611a69575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b15611aa0576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611aa982612095565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b611b336122b3565b6000828152600460205260409020546601000000000000900463ffffffff90811614611b8b576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055602390915290208190611bd982826132b9565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b34082604051611b1f9190613340565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e08401526002909301541692810192909252909114611d48576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314611da5576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b611e4283612095565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff16811115611ea4576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000838152600760205260409020611ebd8284836130c4565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d83836040516108cd929190613228565b600060606000806000634b56a42e60e01b888888604051602401611f1693929190613377565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050611f9f898261059a565b929c919b50995090975095505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa15801561204e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612072919061323c565b61207c919061340d565b905090565b6120896123b2565b61209281612433565b50565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff1633146120f2576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff90811614612092576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146121b9576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b60006121c78383612528565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff1633146121b9576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790526122ae908490612577565b505050565b60175473ffffffffffffffffffffffffffffffffffffffff1633146121b9576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006121c78383612683565b60006bffffffffffffffffffffffff8211156123ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f362062697473000000000000000000000000000000000000000000000000000060648201526084016110f9565b5090565b60005473ffffffffffffffffffffffffffffffffffffffff1633146121b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016110f9565b3373ffffffffffffffffffffffffffffffffffffffff8216036124b2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016110f9565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461256f575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556121ca565b5060006121ca565b60006125d9826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661277d9092919063ffffffff16565b8051909150156122ae57808060200190518101906125f79190613255565b6122ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016110f9565b6000818152600183016020526040812054801561276c5760006126a7600183612f71565b85549091506000906126bb90600190612f71565b90508181146127205760008660000182815481106126db576126db61342d565b90600052602060002001549050808760000184815481106126fe576126fe61342d565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806127315761273161345c565b6001900381819060005260206000200160009055905585600101600086815260200190815260200160002060009055600193505050506121ca565b60009150506121ca565b5092915050565b606061278c8484600085612794565b949350505050565b606082471015612826576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016110f9565b6000808673ffffffffffffffffffffffffffffffffffffffff16858760405161284f9190612f26565b60006040518083038185875af1925050503d806000811461288c576040519150601f19603f3d011682016040523d82523d6000602084013e612891565b606091505b50915091506128a2878383876128ad565b979650505050505050565b6060831561294357825160000361293c5773ffffffffffffffffffffffffffffffffffffffff85163b61293c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016110f9565b508161278c565b61278c83838151156129585781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110f9919061348b565b73ffffffffffffffffffffffffffffffffffffffff8116811461209257600080fd5b600080604083850312156129c157600080fd5b8235915060208301356129d38161298c565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612a5457612a546129de565b604052919050565b600067ffffffffffffffff821115612a7657612a766129de565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112612ab357600080fd5b8135612ac6612ac182612a5c565b612a0d565b818152846020838601011115612adb57600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612b0b57600080fd5b82359150602083013567ffffffffffffffff811115612b2957600080fd5b612b3585828601612aa2565b9150509250929050565b60005b83811015612b5a578181015183820152602001612b42565b50506000910152565b60008151808452612b7b816020860160208601612b3f565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8415158152608060208201526000612bc86080830186612b63565b9050600a8410612c01577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b60008083601f840112612c2557600080fd5b50813567ffffffffffffffff811115612c3d57600080fd5b602083019150836020828501011115612c5557600080fd5b9250929050565b600080600060408486031215612c7157600080fd5b83359250602084013567ffffffffffffffff811115612c8f57600080fd5b612c9b86828701612c13565b9497909650939450505050565b600060208284031215612cba57600080fd5b5035919050565b600080600060608486031215612cd657600080fd5b8335612ce18161298c565b92506020840135612cf18161298c565b929592945050506040919091013590565b60008060408385031215612d1557600080fd5b8235612d208161298c565b946020939093013593505050565b60008060408385031215612d4157600080fd5b8235915060208301356bffffffffffffffffffffffff811681146129d357600080fd5b63ffffffff8116811461209257600080fd5b60008060408385031215612d8957600080fd5b8235915060208301356129d381612d64565b6000808284036060811215612daf57600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082011215612de357600080fd5b506020830190509250929050565b60008060008060608587031215612e0757600080fd5b8435935060208086013567ffffffffffffffff80821115612e2757600080fd5b818801915088601f830112612e3b57600080fd5b813581811115612e4d57612e4d6129de565b8060051b612e5c858201612a0d565b918252838101850191858101908c841115612e7657600080fd5b86860192505b83831015612eb257823585811115612e945760008081fd5b612ea28e89838a0101612aa2565b8352509186019190860190612e7c565b98505050506040880135925080831115612ecb57600080fd5b5050612ed987828801612c13565b95989497509550505050565b600060208284031215612ef757600080fd5b8135612f028161298c565b9392505050565b600060208284031215612f1b57600080fd5b8151612f028161298c565b60008251612f38818460208701612b3f565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156121ca576121ca612f42565b80518015158114612f9457600080fd5b919050565b60008060408385031215612fac57600080fd5b612fb583612f84565b9150602083015167ffffffffffffffff811115612fd157600080fd5b8301601f81018513612fe257600080fd5b8051612ff0612ac182612a5c565b81815286602083850101111561300557600080fd5b613016826020830160208601612b3f565b8093505050509250929050565b600181811c9082168061303757607f821691505b602082108103613070577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f8211156122ae57600081815260208120601f850160051c8101602086101561309d5750805b601f850160051c820191505b818110156130bc578281556001016130a9565b505050505050565b67ffffffffffffffff8311156130dc576130dc6129de565b6130f0836130ea8354613023565b83613076565b6000601f841160018114613142576000851561310c5750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b1783556131d8565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b828110156131915786850135825560209485019460019092019101613171565b50868210156131cc577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60208152600061278c6020830184866131df565b60006020828403121561324e57600080fd5b5051919050565b60006020828403121561326757600080fd5b6121c782612f84565b6bffffffffffffffffffffffff81811683821601908082111561277657612776612f42565b808201808211156121ca576121ca612f42565b62ffffff8116811461209257600080fd5b81356132c481612d64565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000082161783556020840135613304816132a8565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b60408101823561334f81612d64565b63ffffffff1682526020830135613365816132a8565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b838110156133ec577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08887030185526133da868351612b63565b955093820193908201906001016133a0565b5050858403818701525050506134038185876131df565b9695505050505050565b818103600083128015838313168383128216171561277657612776612f42565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6020815260006121c76020830184612b6356fea164736f6c6343000813000a", + 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\":\"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\":\"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\":\"linkAvailableForPayment\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"\",\"type\":\"int256\"}],\"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\":\"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: "0x6101806040523480156200001257600080fd5b5060405162003d8638038062003d8683398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051613655620007316000396000818161016c01526102190152600081816118a20152611afe0152600061230c01526000505060005050600050506000505060008181610bca01528181610c8b01528181610d56015261215e01526136556000f3fe60806040526004361061016a5760003560e01c80638765ecbe116100cb578063a86e17811161007f578063ce7dc5b411610059578063ce7dc5b414610431578063d09dc33914610451578063f2fde38b146104745761016a565b8063a86e1781146103d1578063b148ab6b146103f1578063cd7f71b5146104115761016a565b80638dcf0fe7116100b05780638dcf0fe71461037e578063948108f71461039e578063a72aa27e146103b15761016a565b80638765ecbe146103335780638da5cb5b146103535761016a565b806354b7faae1161012257806371fae17f1161010757806371fae17f146102de578063744bfe61146102fe57806379ba50971461031e5761016a565b806354b7faae1461029e57806368d369d8146102be5761016a565b8063349e8cca11610153578063349e8cca1461020a5780634ee88d351461025e5780635165f2f51461027e5761016a565b80631a2af011146101b157806329c5efad146101d1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e8080156101aa573d6000f35b3d6000fd5b005b3480156101bd57600080fd5b506101af6101cc366004612b58565b610494565b3480156101dd57600080fd5b506101f16101ec366004612ca2565b61059a565b6040516102019493929190612d57565b60405180910390f35b34801561021657600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610201565b34801561026a57600080fd5b506101af610279366004612e06565b610878565b34801561028a57600080fd5b506101af610299366004612e52565b6108da565b3480156102aa57600080fd5b506101af6102b9366004612e6b565b610a8c565b3480156102ca57600080fd5b506101af6102d9366004612e97565b610cff565b3480156102ea57600080fd5b506101af6102f9366004612e52565b610f49565b34801561030a57600080fd5b506101af610319366004612b58565b610fdf565b34801561032a57600080fd5b506101af611457565b34801561033f57600080fd5b506101af61034e366004612e52565b611554565b34801561035f57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610239565b34801561038a57600080fd5b506101af610399366004612e06565b611709565b6101af6103ac366004612ed8565b61175e565b3480156103bd57600080fd5b506101af6103cc366004612f20565b611bd6565b3480156103dd57600080fd5b506101af6103ec366004612f45565b611cd5565b3480156103fd57600080fd5b506101af61040c366004612e52565b611db6565b34801561041d57600080fd5b506101af61042c366004612e06565b611fe3565b34801561043d57600080fd5b506101f161044c366004612f9b565b61209a565b34801561045d57600080fd5b5061046661215c565b604051908152602001610201565b34801561048057600080fd5b506101af61048f36600461308f565b61222b565b61049d8261223f565b3373ffffffffffffffffffffffffffffffffffffffff8216036104ec576040517f8c8728c700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff8281169116146105965760008281526006602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff851690811790915590519091339185917fb1cbb2c4b8480034c27e06da5f096b8233a8fd4497028593a41ff6df79726b3591a45b5050565b600060606000806105a96122f4565b600086815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff620100008204811695830195909552660100000000000081048516606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490941660e0820152600290910154909216908201525a9150600080826080015173ffffffffffffffffffffffffffffffffffffffff1663f00e6a2a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106ff573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061072391906130b3565b73ffffffffffffffffffffffffffffffffffffffff16601660000160149054906101000a900463ffffffff1663ffffffff168960405161076391906130d0565b60006040518083038160008787f1925050503d80600081146107a1576040519150601f19603f3d011682016040523d82523d6000602084013e6107a6565b606091505b50915091505a6107b6908561311b565b9350816107df57600060405180602001604052806000815250600796509650965050505061086f565b808060200190518101906107f39190613143565b90975095508661081f57600060405180602001604052806000815250600496509650965050505061086f565b60185486517401000000000000000000000000000000000000000090910463ffffffff16101561086b57600060405180602001604052806000815250600596509650965050505061086f565b5050505b92959194509250565b6108818361223f565b6000838152601d6020526040902061089a82848361326e565b50827f2b72ac786c97e68dbab71023ed6f2bdbfc80ad9bb7808941929229d71b7d566483836040516108cd9291906133d2565b60405180910390a2505050565b6108e38161223f565b600081815260046020908152604091829020825161012081018452815460ff808216151580845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152610a1d576040517f1b88a78400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055610a5c600283612365565b5060405182907f7bada562044eb163f6b4003c4553e4e62825344c0418eea087bed5ee05a4745690600090a25050565b610a9461237a565b73ffffffffffffffffffffffffffffffffffffffff8216610ae1576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610aeb61215c565b90506000811215610b37576040517fcf47918100000000000000000000000000000000000000000000000000000000815260006004820152602481018390526044015b60405180910390fd5b80821115610b7b576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610b2e565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018490526000917f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015610c15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3991906133e6565b905080610c72576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff167f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa885604051610cf191815260200190565b60405180910390a350505050565b610d0761237a565b73ffffffffffffffffffffffffffffffffffffffff8216610d54576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610dd9576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff83166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa158015610e55573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e799190613401565b610e83919061311b565b905080821115610ec9576040517fcf4791810000000000000000000000000000000000000000000000000000000081526004810182905260248101839052604401610b2e565b610eea73ffffffffffffffffffffffffffffffffffffffff851684846123cb565b8273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa884604051610cf191815260200190565b610f5161245d565b600081815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055602390915280822080547fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000001690555182917f97d0ef3f46a56168af653f547bdb6f77ec2b1d7d9bc6ba0193c2b340ec68064a91a250565b60145477010000000000000000000000000000000000000000000000900460ff1615611037576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000017905573ffffffffffffffffffffffffffffffffffffffff81166110c6576040517f9c8d2cd200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000828152600460209081526040808320815161012081018352815460ff8082161515835261010080830490911615158387015263ffffffff620100008304811684870152660100000000000083048116606085015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009093048316608085015260018501546fffffffffffffffffffffffffffffffff811660a08601526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08601527c010000000000000000000000000000000000000000000000000000000090041660e084015260029093015481169282019290925286855260059093529220549091163314611206576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601554604080517f57e871e7000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916357e871e7916004808201926020929091908290030181865afa158015611276573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061129a9190613401565b816060015163ffffffff1611156112dd576040517fff84e5dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008381526004602090815260408083206001015461010085015173ffffffffffffffffffffffffffffffffffffffff1684526021909252909120547001000000000000000000000000000000009091046bffffffffffffffffffffffff169061134890829061311b565b6101008301805173ffffffffffffffffffffffffffffffffffffffff908116600090815260216020908152604080832095909555888252600490529290922060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff169055516113cb9116846bffffffffffffffffffffffff84166123cb565b604080516bffffffffffffffffffffffff8316815273ffffffffffffffffffffffffffffffffffffffff8516602082015285917ff3b5906e5672f3e524854103bcafbbdba80dbdfeca2c35e116127b1060a68318910160405180910390a25050601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff1690555050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146114d8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610b2e565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61155d8161223f565b600081815260046020908152604091829020825161012081018452815460ff808216158015845261010080840490921615159584019590955262010000820463ffffffff9081169684019690965266010000000000008204861660608401526a010000000000000000000090910473ffffffffffffffffffffffffffffffffffffffff908116608084015260018401546fffffffffffffffffffffffffffffffff811660a085015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08501527c0100000000000000000000000000000000000000000000000000000000900490951660e083015260029092015490931690830152611697576040517f514b6c2400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556116d96002836124ae565b5060405182907f8ab10247ce168c27748e656ecf852b951fcaac790c18106b19aa0ae57a8b741f90600090a25050565b6117128361223f565b6000838152601e6020526040902061172b82848361326e565b50827f3e8740446213c8a77d40e08f79136ce3f347d13ed270a6ebdf57159e0faf485083836040516108cd9291906133d2565b600082815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e0840152600290930154169281019290925290911461189a576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3415611936577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1681610100015173ffffffffffffffffffffffffffffffffffffffff161461192a576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611933346124ba565b91505b818160c00151611946919061341a565b600084815260046020908152604080832060010180547fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff167001000000000000000000000000000000006bffffffffffffffffffffffff9687160217905561010085015173ffffffffffffffffffffffffffffffffffffffff16835260219091529020546119d69184169061343f565b61010082015173ffffffffffffffffffffffffffffffffffffffff16600090815260216020526040812091909155349003611afc576101008101516040517f23b872dd0000000000000000000000000000000000000000000000000000000081523360048201523060248201526bffffffffffffffffffffffff8416604482015260009173ffffffffffffffffffffffffffffffffffffffff16906323b872dd906064016020604051808303816000875af1158015611a99573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611abd91906133e6565b905080611af6576040517f90b8ec1800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50611b8c565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0836bffffffffffffffffffffffff166040518263ffffffff1660e01b81526004016000604051808303818588803b158015611b7257600080fd5b505af1158015611b86573d6000803e3d6000fd5b50505050505b6040516bffffffffffffffffffffffff83168152339084907fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa7348915062039060200160405180910390a3505050565b6108fc8163ffffffff161080611c13575060165463ffffffff78010000000000000000000000000000000000000000000000009091048116908216115b15611c4a576040517f14c237fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611c538261223f565b60008281526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffff166201000063ffffffff861690810291909117909155915191825283917fc24c07e655ce79fba8a589778987d3c015bc6af1632bb20cf9182e02a65d972c91015b60405180910390a25050565b611cdd61245d565b6000828152600460205260409020546601000000000000900463ffffffff90811614611d35576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600082815260046020908152604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff16610100179055602390915290208190611d838282613463565b905050817fd8a6d79d170a55968079d3a89b960d86b4442aef6aac1d01e644c32b9e38b34082604051611cc991906134ea565b600081815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615159483019490945263ffffffff6201000082048116958301959095526601000000000000810485166060830181905273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009092048216608084015260018401546fffffffffffffffffffffffffffffffff811660a08501526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08501527c01000000000000000000000000000000000000000000000000000000009004861660e08401526002909301541692810192909252909114611ef2576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526006602052604090205473ffffffffffffffffffffffffffffffffffffffff163314611f4f576040517f6352a85300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008281526005602090815260408083208054337fffffffffffffffffffffffff0000000000000000000000000000000000000000808316821790935560069094528285208054909216909155905173ffffffffffffffffffffffffffffffffffffffff90911692839186917f5cff4db96bef051785e999f44bfcd21c18823e034fb92dd376e3db4ce0feeb2c91a4505050565b611fec8361223f565b6017547c0100000000000000000000000000000000000000000000000000000000900463ffffffff1681111561204e576040517fae7235df00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600083815260076020526040902061206782848361326e565b50827fcba2d5723b2ee59e53a8e8a82a4a7caf4fdfe70e9f7c582950bf7e7a5c24e83d83836040516108cd9291906133d2565b600060606000806000634b56a42e60e01b8888886040516024016120c093929190613521565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909316929092179091529050612149898261059a565b929c919b50995090975095505050505050565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166000818152602160205260408082205490517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919290916370a0823190602401602060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221c9190613401565b61222691906135b7565b905090565b61223361255c565b61223c816125dd565b50565b60008181526005602052604090205473ffffffffffffffffffffffffffffffffffffffff16331461229c576040517fa47c170600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020546601000000000000900463ffffffff9081161461223c576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612363576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b565b600061237183836126d2565b90505b92915050565b60185473ffffffffffffffffffffffffffffffffffffffff163314612363576040517fb6dfb7a600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052612458908490612721565b505050565b60175473ffffffffffffffffffffffffffffffffffffffff163314612363576040517f77c3599200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612371838361282d565b60006bffffffffffffffffffffffff821115612558576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610b2e565b5090565b60005473ffffffffffffffffffffffffffffffffffffffff163314612363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610b2e565b3373ffffffffffffffffffffffffffffffffffffffff82160361265c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610b2e565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b600081815260018301602052604081205461271957508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155612374565b506000612374565b6000612783826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166129279092919063ffffffff16565b80519091501561245857808060200190518101906127a191906133e6565b612458576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610b2e565b6000818152600183016020526040812054801561291657600061285160018361311b565b85549091506000906128659060019061311b565b90508181146128ca576000866000018281548110612885576128856135d7565b90600052602060002001549050808760000184815481106128a8576128a86135d7565b6000918252602080832090910192909255918252600188019052604090208390555b85548690806128db576128db613606565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050612374565b6000915050612374565b5092915050565b6060612936848460008561293e565b949350505050565b6060824710156129d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610b2e565b6000808673ffffffffffffffffffffffffffffffffffffffff1685876040516129f991906130d0565b60006040518083038185875af1925050503d8060008114612a36576040519150601f19603f3d011682016040523d82523d6000602084013e612a3b565b606091505b5091509150612a4c87838387612a57565b979650505050505050565b60608315612aed578251600003612ae65773ffffffffffffffffffffffffffffffffffffffff85163b612ae6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610b2e565b5081612936565b6129368383815115612b025781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9190613635565b73ffffffffffffffffffffffffffffffffffffffff8116811461223c57600080fd5b60008060408385031215612b6b57600080fd5b823591506020830135612b7d81612b36565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612bfe57612bfe612b88565b604052919050565b600067ffffffffffffffff821115612c2057612c20612b88565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f830112612c5d57600080fd5b8135612c70612c6b82612c06565b612bb7565b818152846020838601011115612c8557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060408385031215612cb557600080fd5b82359150602083013567ffffffffffffffff811115612cd357600080fd5b612cdf85828601612c4c565b9150509250929050565b60005b83811015612d04578181015183820152602001612cec565b50506000910152565b60008151808452612d25816020860160208601612ce9565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8415158152608060208201526000612d726080830186612d0d565b9050600a8410612dab577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60408201939093526060015292915050565b60008083601f840112612dcf57600080fd5b50813567ffffffffffffffff811115612de757600080fd5b602083019150836020828501011115612dff57600080fd5b9250929050565b600080600060408486031215612e1b57600080fd5b83359250602084013567ffffffffffffffff811115612e3957600080fd5b612e4586828701612dbd565b9497909650939450505050565b600060208284031215612e6457600080fd5b5035919050565b60008060408385031215612e7e57600080fd5b8235612e8981612b36565b946020939093013593505050565b600080600060608486031215612eac57600080fd5b8335612eb781612b36565b92506020840135612ec781612b36565b929592945050506040919091013590565b60008060408385031215612eeb57600080fd5b8235915060208301356bffffffffffffffffffffffff81168114612b7d57600080fd5b63ffffffff8116811461223c57600080fd5b60008060408385031215612f3357600080fd5b823591506020830135612b7d81612f0e565b6000808284036060811215612f5957600080fd5b8335925060407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082011215612f8d57600080fd5b506020830190509250929050565b60008060008060608587031215612fb157600080fd5b8435935060208086013567ffffffffffffffff80821115612fd157600080fd5b818801915088601f830112612fe557600080fd5b813581811115612ff757612ff7612b88565b8060051b613006858201612bb7565b918252838101850191858101908c84111561302057600080fd5b86860192505b8383101561305c5782358581111561303e5760008081fd5b61304c8e89838a0101612c4c565b8352509186019190860190613026565b9850505050604088013592508083111561307557600080fd5b505061308387828801612dbd565b95989497509550505050565b6000602082840312156130a157600080fd5b81356130ac81612b36565b9392505050565b6000602082840312156130c557600080fd5b81516130ac81612b36565b600082516130e2818460208701612ce9565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b81810381811115612374576123746130ec565b8051801515811461313e57600080fd5b919050565b6000806040838503121561315657600080fd5b61315f8361312e565b9150602083015167ffffffffffffffff81111561317b57600080fd5b8301601f8101851361318c57600080fd5b805161319a612c6b82612c06565b8181528660208385010111156131af57600080fd5b6131c0826020830160208601612ce9565b8093505050509250929050565b600181811c908216806131e157607f821691505b60208210810361321a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561245857600081815260208120601f850160051c810160208610156132475750805b601f850160051c820191505b8181101561326657828155600101613253565b505050505050565b67ffffffffffffffff83111561328657613286612b88565b61329a8361329483546131cd565b83613220565b6000601f8411600181146132ec57600085156132b65750838201355b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b1c1916600186901b178355613382565b6000838152602090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0861690835b8281101561333b578685013582556020948501946001909201910161331b565b5086821015613376577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b602081526000612936602083018486613389565b6000602082840312156133f857600080fd5b6123718261312e565b60006020828403121561341357600080fd5b5051919050565b6bffffffffffffffffffffffff818116838216019080821115612920576129206130ec565b80820180821115612374576123746130ec565b62ffffff8116811461223c57600080fd5b813561346e81612f0e565b63ffffffff811690508154817fffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000821617835560208401356134ae81613452565b66ffffff000000008160201b16837fffffffffffffffffffffffffffffffffffffffffffffffffff000000000000008416171784555050505050565b6040810182356134f981612f0e565b63ffffffff168252602083013561350f81613452565b62ffffff811660208401525092915050565b6000604082016040835280865180835260608501915060608160051b8601019250602080890160005b83811015613596577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa0888703018552613584868351612d0d565b9550938201939082019060010161354a565b5050858403818701525050506135ad818587613389565b9695505050505050565b8181036000831280158383131683831282161715612920576129206130ec565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6020815260006123716020830184612d0d56fea164736f6c6343000813000a", } var AutomationRegistryLogicBABI = AutomationRegistryLogicBMetaData.ABI @@ -430,16 +430,16 @@ func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) Unpa return _AutomationRegistryLogicB.Contract.UnpauseUpkeep(&_AutomationRegistryLogicB.TransactOpts, id) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) WithdrawERC20Fees(opts *bind.TransactOpts, assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.contract.Transact(opts, "withdrawERC20Fees", assetAddress, to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) WithdrawERC20Fees(opts *bind.TransactOpts, asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.contract.Transact(opts, "withdrawERC20Fees", asset, to, amount) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBSession) WithdrawERC20Fees(assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.Contract.WithdrawERC20Fees(&_AutomationRegistryLogicB.TransactOpts, assetAddress, to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBSession) WithdrawERC20Fees(asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.Contract.WithdrawERC20Fees(&_AutomationRegistryLogicB.TransactOpts, asset, to, amount) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) WithdrawERC20Fees(assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.Contract.WithdrawERC20Fees(&_AutomationRegistryLogicB.TransactOpts, assetAddress, to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) WithdrawERC20Fees(asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.Contract.WithdrawERC20Fees(&_AutomationRegistryLogicB.TransactOpts, asset, to, amount) } func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) { @@ -454,16 +454,16 @@ func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) With return _AutomationRegistryLogicB.Contract.WithdrawFunds(&_AutomationRegistryLogicB.TransactOpts, id, to) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) WithdrawLinkFees(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.contract.Transact(opts, "withdrawLinkFees", to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) WithdrawLink(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.contract.Transact(opts, "withdrawLink", to, amount) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBSession) WithdrawLinkFees(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.Contract.WithdrawLinkFees(&_AutomationRegistryLogicB.TransactOpts, to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBSession) WithdrawLink(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.Contract.WithdrawLink(&_AutomationRegistryLogicB.TransactOpts, to, amount) } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) WithdrawLinkFees(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _AutomationRegistryLogicB.Contract.WithdrawLinkFees(&_AutomationRegistryLogicB.TransactOpts, to, amount) +func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactorSession) WithdrawLink(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _AutomationRegistryLogicB.Contract.WithdrawLink(&_AutomationRegistryLogicB.TransactOpts, to, amount) } func (_AutomationRegistryLogicB *AutomationRegistryLogicBTransactor) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) { @@ -1422,42 +1422,42 @@ func (it *AutomationRegistryLogicBFeesWithdrawnIterator) Close() error { } type AutomationRegistryLogicBFeesWithdrawn struct { - Recipient common.Address AssetAddress common.Address + Recipient common.Address Amount *big.Int Raw types.Log } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryLogicBFeesWithdrawnIterator, error) { +func (_AutomationRegistryLogicB *AutomationRegistryLogicBFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicBFeesWithdrawnIterator, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistryLogicB.contract.FilterLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistryLogicB.contract.FilterLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } return &AutomationRegistryLogicBFeesWithdrawnIterator{contract: _AutomationRegistryLogicB.contract, event: "FeesWithdrawn", logs: logs, sub: sub}, nil } -func (_AutomationRegistryLogicB *AutomationRegistryLogicBFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicBFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) { +func (_AutomationRegistryLogicB *AutomationRegistryLogicBFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicBFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistryLogicB.contract.WatchLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistryLogicB.contract.WatchLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } @@ -5438,11 +5438,11 @@ type AutomationRegistryLogicBInterface interface { UnpauseUpkeep(opts *bind.TransactOpts, id *big.Int) (*types.Transaction, error) - WithdrawERC20Fees(opts *bind.TransactOpts, assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) + WithdrawERC20Fees(opts *bind.TransactOpts, asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) - WithdrawLinkFees(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) + WithdrawLink(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) Fallback(opts *bind.TransactOpts, calldata []byte) (*types.Transaction, error) @@ -5488,9 +5488,9 @@ type AutomationRegistryLogicBInterface interface { ParseDedupKeyAdded(log types.Log) (*AutomationRegistryLogicBDedupKeyAdded, error) - FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryLogicBFeesWithdrawnIterator, error) + FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryLogicBFeesWithdrawnIterator, error) - WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicBFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) + WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryLogicBFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) ParseFeesWithdrawn(log types.Log) (*AutomationRegistryLogicBFeesWithdrawn, error) 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 ff3bf0f6bf1..60f92fe384f 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 @@ -63,8 +63,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\":\"int256\",\"name\":\"available\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"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\":\"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\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"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\":\"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\":\"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: "0x6101806040523480156200001257600080fd5b50604051620063b8380380620063b883398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615c88620007306000396000818160c9015261017c015260005050600061226a015260005050600050506000613a9e01526000505060008181610df301528181610f010152818161102c01528181611076015261176f0152615c886000f3fe6080604052600436106100c75760003560e01c8063a4c0ed3611610074578063b1dc65a41161004e578063b1dc65a414610338578063e3d0e71214610358578063f2fde38b14610378576100c7565b8063a4c0ed361461029b578063aed2e929146102bb578063afcb95d7146102f2576100c7565b80637bee169d116100a55780637bee169d146101d657806381ff7048146101f65780638da5cb5b14610270576100c7565b8063181f5a771461010e578063349e8cca1461016d57806379ba5097146101c1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610107573d6000f35b3d6000fd5b005b34801561011a57600080fd5b506101576040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b604051610164919061462f565b60405180910390f35b34801561017957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b3480156101cd57600080fd5b5061010c610398565b3480156101e257600080fd5b5061010c6101f1366004614ba4565b61049a565b34801561020257600080fd5b5061024d60175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610164565b34801561027c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661019c565b3480156102a757600080fd5b5061010c6102b6366004614d05565b610ddb565b3480156102c757600080fd5b506102db6102d6366004614d61565b6110f7565b604080519215158352602083019190915201610164565b3480156102fe57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610164565b34801561034457600080fd5b5061010c610353366004614df2565b6112a2565b34801561036457600080fd5b5061010c610373366004614ea9565b611583565b34801561038457600080fd5b5061010c610393366004614f76565b6115bd565b60015473ffffffffffffffffffffffffffffffffffffffff16331461041e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104a26115d1565b601f885111156104de576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff1660000361051b576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8651885114158061053a5750610532866003614fc9565b60ff16885111155b15610571576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80518251146105ac576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105b68282611654565b6105c08888611abc565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bea9190614fe5565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610c6191859174010000000000000000000000000000000000000000900416614ffe565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610c92919061506c565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610cf7904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d61217d565b601355600960008181610d0a8282614516565b5050505060005b876101c0015151811015610d6457610d51886101c001518281518110610d3957610d396151f2565b6020026020010151600961222790919063ffffffff16565b5080610d5c81615221565b915050610d11565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610dc79286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f90615259565b60405180910390a150505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e4a576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e84576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e92828401846152ef565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610eed576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f71576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610fb090859070010000000000000000000000000000000090046bffffffffffffffffffffffff16615308565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016825260219052205461105f90859061532d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b600080611102612252565b601454760100000000000000000000000000000000000000000000900460ff1615611159576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936112959389908990819084018382808284376000920191909152506122c192505050565b9097909650945050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152919250611406576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff1661144f576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a351461148b576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608081015161149b906001615340565b60ff16861415806114ac5750858414155b156114e3576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114f38a8a8a8a8a8a8a8a6124dc565b60006114ff8a8a612745565b905060208b0135600881901c63ffffffff1661151c8484876127fe565b836020015163ffffffff168163ffffffff16111561157457601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b60008060008580602001905181019061159c9190615517565b9250925092506115b2898989868989888861049a565b505050505050505050565b6115c56115d1565b6115ce81613309565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610415565b565b60005b602454811015611712576022600060248381548110611678576116786151f2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffff000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061170a81615221565b915050611657565b5061171f60246000614516565b60255460ff1660005b8351811015611ab6576000848281518110611745576117456151f2565b602002602001015190506000848381518110611763576117636151f2565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156117d9575060018460018111156117d7576117d76156c2565b145b15611810576040517f1183afea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061184b5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611882576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156118ec576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018082019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec40180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8581169182179092556000818152602260209081526040918290208651815488840180518a8701805163ffffffff9095167fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000909416841764010000000062ffffff93841602177fffffffffff0000000000000000000000000000000000000000ffffffffffffff16670100000000000000958b16959095029490941785556060808c0180519b87019b909b556080808d018051600290980180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff998a1617905589519586529351909216968401969096529251909716948101949094529551918301919091529251909216928201929092527f720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c9060a00160405180910390a250508080611aae90615221565b915050611728565b50505050565b60005b600e54811015611b3357611b20600e8281548110611adf57611adf6151f2565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff909116906133fe565b5080611b2b81615221565b915050611abf565b5060255460009060ff16815b600e54811015611ca457600e8181548110611b5c57611b5c6151f2565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611b9957611b996151f2565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611c3b57611c3b6156c2565b148015611c80575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611c9257611c90600f84612227565b505b80611c9c81615221565b915050611b3f565b50611cb1600d6000614516565b611cbd600e6000614516565b6040805160808101825260008082526020820181905291810182905260608101829052905b855181101561214d57600c6000878381518110611d0157611d016151f2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611d6c576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611d9657611d966151f2565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611deb576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611e1c57611e1c6151f2565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611ec457611ec46151f2565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611f34576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611fef576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000090951694909417179190911692909217919091179055836001811115612129576121296156c2565b0361213b57612139600f85613606565b505b8061214581615221565b915050611ce2565b50845161216190600d906020880190614534565b50835161217590600e906020870190614534565b505050505050565b6000808a8a8a8a8a8a8a8a8a6040516020016121a1999897969594939291906156f1565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b60006122498373ffffffffffffffffffffffffffffffffffffffff8416613628565b90505b92915050565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611652576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600090819077010000000000000000000000000000000000000000000000900460ff161561231e576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061239390859060240161462f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d16906124669087908790600401615786565b60408051808303816000875af1158015612484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a8919061579f565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b600087876040516124ee9291906157cd565b604051908190038120612505918b906020016157dd565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b888110156126dc57600185878360208110612571576125716151f2565b61257e91901a601b615340565b8c8c85818110612590576125906151f2565b905060200201358b8b868181106125a9576125a96151f2565b90506020020135604051600081526020016040526040516125e6949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612608573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff80821615158085526101009092041693830193909352909550935090506126b6576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b8401935080806126d490615221565b915050612554565b50827e01010101010101010101010101010101010101010101010101010101010101841614612737576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b61277e6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b600061278c838501856158ce565b60408101515160608201515191925090811415806127af57508082608001515114155b806127bf5750808260a001515114155b156127f6576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561281e5761281e614642565b6040519080825280602002602001820160405280156128ea57816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161283c5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612988573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ac9190614fe5565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a249190614fe5565b905060005b866040015151811015612eb4576004600088604001518381518110612a5057612a506151f2565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e0820152600290910154909116918101919091528551869083908110612b7357612b736151f2565b602002602001015160000181905250612ba887604001518281518110612b9b57612b9b6151f2565b6020026020010151613677565b858281518110612bba57612bba6151f2565b6020026020010151606001906001811115612bd757612bd76156c2565b90816001811115612bea57612bea6156c2565b81525050612c4e87604001518281518110612c0757612c076151f2565b60200260200101518489608001518481518110612c2657612c266151f2565b6020026020010151888581518110612c4057612c406151f2565b60200260200101518c613722565b868381518110612c6057612c606151f2565b6020026020010151602001878481518110612c7d57612c7d6151f2565b602002602001015160c0018281525082151515158152505050848181518110612ca857612ca86151f2565b60200260200101516020015115612cd857600184600001818151612ccc91906159bb565b61ffff16905250612cdd565b612ea2565b612d43858281518110612cf257612cf26151f2565b6020026020010151600001516080015188606001518381518110612d1857612d186151f2565b60200260200101518960a001518481518110612d3657612d366151f2565b60200260200101516122c1565b868381518110612d5557612d556151f2565b6020026020010151604001878481518110612d7257612d726151f2565b6020026020010151608001828152508215151515815250505087608001516001612d9c9190615340565b612daa9060ff1660406159d6565b6103a48860a001518381518110612dc357612dc36151f2565b602002602001015151612dd6919061532d565b612de0919061532d565b858281518110612df257612df26151f2565b602002602001015160a0018181525050848181518110612e1457612e146151f2565b602002602001015160a0015184606001818151612e31919061532d565b9052508451859082908110612e4857612e486151f2565b60200260200101516080015186612e5f91906159ed565b9550612ea287604001518281518110612e7a57612e7a6151f2565b602002602001015184878481518110612e9557612e956151f2565b6020026020010151613841565b80612eac81615221565b915050612a29565b50825161ffff16600003612ecb5750505050505050565b6155f0612ed93660106159d6565b5a612ee490886159ed565b612eee919061532d565b612ef8919061532d565b8351909550611b5890612f0f9061ffff1687615a2f565b612f19919061532d565b604080516060810182526000808252602082018190529181018290529196505b87604001515181101561323857858181518110612f5857612f586151f2565b6020026020010151602001511561322657801580612ff0575085612f7d6001836159ed565b81518110612f8d57612f8d6151f2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16868281518110612fc657612fc66151f2565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b15613024576130218987838151811061300b5761300b6151f2565b6020026020010151600001516101000151613946565b91505b600061310a8a6040518061010001604052808a8681518110613048576130486151f2565b60200260200101516080015181526020018b815260200189606001518b8781518110613076576130766151f2565b602002602001015160a001518961308d91906159d6565b6130979190615a2f565b81526020018c6000015181526020018c6020015181526020016130b98e613a97565b81526020810187905260016040918201528c01518051869081106130df576130df6151f2565b60200260200101518a86815181106130f9576130f96151f2565b602002602001015160000151613b88565b90508060600151866040018181516131229190615308565b6bffffffffffffffffffffffff169052506040810151602087018051613149908390615308565b6bffffffffffffffffffffffff16905250865187908390811061316e5761316e6151f2565b602002602001015160400151151589604001518381518110613192576131926151f2565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b836060015184604001516131cf9190615308565b8a86815181106131e1576131e16151f2565b6020026020010151608001518c8e608001518881518110613204576132046151f2565b602002602001015160405161321c9493929190615a43565b60405180910390a3505b8061323081615221565b915050612f39565b5050602083810151336000908152600b909252604090912080546002906132749084906201000090046bffffffffffffffffffffffff16615308565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff166132d29190615308565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff16021790555050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613388576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610415565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906135fa5760008160600151856134969190615a80565b905060006134a48583615aa5565b905080836040018181516134b89190615308565b6bffffffffffffffffffffffff169052506134d38582615ad0565b836060018181516134e49190615308565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60006122498373ffffffffffffffffffffffffffffffffffffffff8416613e20565b600081815260018301602052604081205461366f5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561224c565b50600061224c565b6000818160045b600f811015613704577fff0000000000000000000000000000000000000000000000000000000000000082168382602081106136bc576136bc6151f2565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146136f257506000949350505050565b806136fc81615221565b91505061367e565b5081600f1a600181111561371a5761371a6156c2565b949350505050565b60008080808560600151600181111561373d5761373d6156c2565b036137635761374f8888888888613f13565b61375e57600092509050613837565b6137db565b60018560600151600181111561377b5761377b6156c2565b036137a957600061378e8989898861409d565b92509050806137a35750600092509050613837565b506137db565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061383057877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd56368760405161381d919061462f565b60405180910390a2600092509050613837565b6001925090505b9550959350505050565b600081606001516001811115613859576138596156c2565b036138bd57600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156138d5576138d56156c2565b036139415760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa158015613a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a2c9190615b1a565b50935050925050600082131580613a4257508042105b80613a7257506000866040015162ffffff16118015613a725750613a6681426159ed565b866040015162ffffff16105b15613a865760018301546040850152613a8e565b604084018290525b50505092915050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613b07573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b2b9190615b1a565b50935050925050600082131580613b4157508042105b80613b7157506000846040015162ffffff16118015613b715750613b6581426159ed565b846040015162ffffff16105b15613b81575050601b5492915050565b5092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613c015760008381526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845260c088018051919091529251925192169101525b6000613c0d86866142aa565b60c0840151602082015182519293509091600091613c2a91615308565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613caf57819050613c9087608001518860c0015160400151846bffffffffffffffffffffffff16613c8191906159d6565b613c8b9190615a2f565b614474565b6bffffffffffffffffffffffff16604084015260006060840152613d3b565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613d3b57819050613d2783604001516bffffffffffffffffffffffff1688608001518960c0015160400151856bffffffffffffffffffffffff16613d1391906159d6565b613d1d9190615a2f565b613c8b91906159ed565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613d8190849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615a80565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613ddc9084906fffffffffffffffffffffffffffffffff16615b6a565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550829350505050949350505050565b60008181526001830160205260408120548015613f09576000613e446001836159ed565b8554909150600090613e58906001906159ed565b9050818114613ebd576000866000018281548110613e7857613e786151f2565b9060005260206000200154905080876000018481548110613e9b57613e9b6151f2565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080613ece57613ece615b93565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061224c565b600091505061224c565b60008084806020019051810190613f2a9190615bc2565b845160e00151815191925063ffffffff90811691161015613f8757867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e886604051613f75919061462f565b60405180910390a26000915050614094565b8260e00151801561404757506020810151158015906140475750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa158015614020573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140449190614fe5565b14155b806140595750805163ffffffff168611155b1561408e57867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc30186604051613f75919061462f565b60019150505b95945050505050565b6000806000848060200190518101906140b69190615c1a565b905060008782600001518360200151846040015160405160200161411894939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e0015180156141f357506080820151158015906141f35750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa1580156141cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141f09190614fe5565b14155b80614208575086826060015163ffffffff1610155b1561425257877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018760405161423d919061462f565b60405180910390a26000935091506142a19050565b60008181526008602052604090205460ff161561429957877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88760405161423d919061462f565b600193509150505b94509492505050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff1683606001516142e891906159d6565b90508260e0015180156142fa5750803a105b1561430257503a5b60008360a00151846040015185602001518660000151614322919061532d565b61432c90856159d6565b614336919061532d565b61434091906159d6565b90506143598460c001516040015182613c8b9190615a2f565b6bffffffffffffffffffffffff168352608084015161437c90613c8b9083615a2f565b6bffffffffffffffffffffffff16604084015260c0840151602001516000906143b39062ffffff16683635c9adc5dea000006159d6565b9050600081633b9aca008760a001518860c001516000015163ffffffff1689604001518a60000151896143e691906159d6565b6143f0919061532d565b6143fa91906159d6565b61440491906159d6565b61440e9190615a2f565b614418919061532d565b90506144318660c001516040015182613c8b9190615a2f565b6bffffffffffffffffffffffff166020860152608086015161445790613c8b9083615a2f565b6bffffffffffffffffffffffff1660608601525050505092915050565b60006bffffffffffffffffffffffff821115614512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610415565b5090565b50805460008255906000526020600020908101906115ce91906145b6565b8280548282559060005260206000209081019282156145ae579160200282015b828111156145ae57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614554565b506145129291505b5b8082111561451257600081556001016145b7565b6000815180845260005b818110156145f1576020818501810151868301820152016145d5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b60208152600061224960208301846145cb565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff8111828210171561469557614695614642565b60405290565b60405160a0810167ffffffffffffffff8111828210171561469557614695614642565b60405160c0810167ffffffffffffffff8111828210171561469557614695614642565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561472857614728614642565b604052919050565b600067ffffffffffffffff82111561474a5761474a614642565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146115ce57600080fd5b803561478181614754565b919050565b600082601f83011261479757600080fd5b813560206147ac6147a783614730565b6146e1565b82815260059290921b840181019181810190868411156147cb57600080fd5b8286015b848110156147ef5780356147e281614754565b83529183019183016147cf565b509695505050505050565b803560ff8116811461478157600080fd5b63ffffffff811681146115ce57600080fd5b80356147818161480b565b80151581146115ce57600080fd5b803561478181614828565b62ffffff811681146115ce57600080fd5b803561478181614841565b61ffff811681146115ce57600080fd5b80356147818161485d565b6000610200828403121561488b57600080fd5b614893614671565b905061489e8261481d565b81526148ac6020830161481d565b60208201526148bd6040830161481d565b60408201526148ce60608301614776565b60608201526148df60808301614836565b60808201526148f060a08301614852565b60a082015261490160c0830161481d565b60c082015261491260e0830161481d565b60e0820152610100614925818401614776565b9082015261012061493783820161486d565b90820152610140614949838201614776565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff81111561498a57600080fd5b61499685828601614786565b8284015250506101e06149aa818401614776565b9082015292915050565b803567ffffffffffffffff8116811461478157600080fd5b600082601f8301126149dd57600080fd5b813567ffffffffffffffff8111156149f7576149f7614642565b614a2860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116016146e1565b818152846020838601011115614a3d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112614a6b57600080fd5b81356020614a7b6147a783614730565b82815260059290921b84018101918181019086841115614a9a57600080fd5b8286015b848110156147ef578035614ab181614754565b8352918301918301614a9e565b6bffffffffffffffffffffffff811681146115ce57600080fd5b600082601f830112614ae957600080fd5b81356020614af96147a783614730565b82815260a09283028501820192828201919087851115614b1857600080fd5b8387015b85811015614b975781818a031215614b345760008081fd5b614b3c61469b565b8135614b478161480b565b815281860135614b5681614841565b81870152604082810135614b6981614754565b9082015260608281013590820152608080830135614b8681614abe565b908201528452928401928101614b1c565b5090979650505050505050565b600080600080600080600080610100898b031215614bc157600080fd5b883567ffffffffffffffff80821115614bd957600080fd5b614be58c838d01614786565b995060208b0135915080821115614bfb57600080fd5b614c078c838d01614786565b9850614c1560408c016147fa565b975060608b0135915080821115614c2b57600080fd5b614c378c838d01614878565b9650614c4560808c016149b4565b955060a08b0135915080821115614c5b57600080fd5b614c678c838d016149cc565b945060c08b0135915080821115614c7d57600080fd5b614c898c838d01614a5a565b935060e08b0135915080821115614c9f57600080fd5b50614cac8b828c01614ad8565b9150509295985092959890939650565b60008083601f840112614cce57600080fd5b50813567ffffffffffffffff811115614ce657600080fd5b602083019150836020828501011115614cfe57600080fd5b9250929050565b60008060008060608587031215614d1b57600080fd5b8435614d2681614754565b935060208501359250604085013567ffffffffffffffff811115614d4957600080fd5b614d5587828801614cbc565b95989497509550505050565b600080600060408486031215614d7657600080fd5b83359250602084013567ffffffffffffffff811115614d9457600080fd5b614da086828701614cbc565b9497909650939450505050565b60008083601f840112614dbf57600080fd5b50813567ffffffffffffffff811115614dd757600080fd5b6020830191508360208260051b8501011115614cfe57600080fd5b60008060008060008060008060e0898b031215614e0e57600080fd5b606089018a811115614e1f57600080fd5b8998503567ffffffffffffffff80821115614e3957600080fd5b614e458c838d01614cbc565b909950975060808b0135915080821115614e5e57600080fd5b614e6a8c838d01614dad565b909750955060a08b0135915080821115614e8357600080fd5b50614e908b828c01614dad565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c08789031215614ec257600080fd5b863567ffffffffffffffff80821115614eda57600080fd5b614ee68a838b01614786565b97506020890135915080821115614efc57600080fd5b614f088a838b01614786565b9650614f1660408a016147fa565b95506060890135915080821115614f2c57600080fd5b614f388a838b016149cc565b9450614f4660808a016149b4565b935060a0890135915080821115614f5c57600080fd5b50614f6989828a016149cc565b9150509295509295509295565b600060208284031215614f8857600080fd5b8135614f9381614754565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160290811690818114613b8157613b81614f9a565b600060208284031215614ff757600080fd5b5051919050565b63ffffffff818116838216019080821115613b8157613b81614f9a565b600081518084526020808501945080840160005b8381101561506157815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161502f565b509495945050505050565b6020815261508360208201835163ffffffff169052565b6000602083015161509c604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e083015161010061511b8185018363ffffffff169052565b84015190506101206151448482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151905061014061515b8482018361ffff169052565b84015190506101606151848482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e0808601829052919250906151cc61022086018461501b565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361525257615252614f9a565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526152898184018a61501b565b9050828103608084015261529d818961501b565b905060ff871660a084015282810360c08401526152ba81876145cb565b905067ffffffffffffffff851660e08401528281036101008401526152df81856145cb565b9c9b505050505050505050505050565b60006020828403121561530157600080fd5b5035919050565b6bffffffffffffffffffffffff818116838216019080821115613b8157613b81614f9a565b8082018082111561224c5761224c614f9a565b60ff818116838216019081111561224c5761224c614f9a565b80516147818161480b565b805161478181614754565b805161478181614828565b805161478181614841565b80516147818161485d565b600082601f8301126153a157600080fd5b815160206153b16147a783614730565b82815260059290921b840181019181810190868411156153d057600080fd5b8286015b848110156147ef5780516153e781614754565b83529183019183016153d4565b600082601f83011261540557600080fd5b815160206154156147a783614730565b82815260059290921b8401810191818101908684111561543457600080fd5b8286015b848110156147ef57805161544b81614754565b8352918301918301615438565b600082601f83011261546957600080fd5b815160206154796147a783614730565b82815260a0928302850182019282820191908785111561549857600080fd5b8387015b85811015614b975781818a0312156154b45760008081fd5b6154bc61469b565b81516154c78161480b565b8152818601516154d681614841565b818701526040828101516154e981614754565b908201526060828101519082015260808083015161550681614abe565b90820152845292840192810161549c565b60008060006060848603121561552c57600080fd5b835167ffffffffffffffff8082111561554457600080fd5b90850190610200828803121561555957600080fd5b615561614671565b61556a83615359565b815261557860208401615359565b602082015261558960408401615359565b604082015261559a60608401615364565b60608201526155ab6080840161536f565b60808201526155bc60a0840161537a565b60a08201526155cd60c08401615359565b60c08201526155de60e08401615359565b60e08201526101006155f1818501615364565b90820152610120615603848201615385565b90820152610140615615848201615364565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561564e57600080fd5b61565a8a828701615390565b8284015250506101e061566e818501615364565b90820152602087015190955091508082111561568957600080fd5b615695878388016153f4565b935060408601519150808211156156ab57600080fd5b506156b886828701615458565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526157388285018b61501b565b9150838203608085015261574c828a61501b565b915060ff881660a085015283820360c085015261576982886145cb565b90861660e085015283810361010085015290506152df81856145cb565b82815260406020820152600061371a60408301846145cb565b600080604083850312156157b257600080fd5b82516157bd81614828565b6020939093015192949293505050565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261580457600080fd5b813560206158146147a783614730565b82815260059290921b8401810191818101908684111561583357600080fd5b8286015b848110156147ef5780358352918301918301615837565b600082601f83011261585f57600080fd5b8135602061586f6147a783614730565b82815260059290921b8401810191818101908684111561588e57600080fd5b8286015b848110156147ef57803567ffffffffffffffff8111156158b25760008081fd5b6158c08986838b01016149cc565b845250918301918301615892565b6000602082840312156158e057600080fd5b813567ffffffffffffffff808211156158f857600080fd5b9083019060c0828603121561590c57600080fd5b6159146146be565b823581526020830135602082015260408301358281111561593457600080fd5b615940878286016157f3565b60408301525060608301358281111561595857600080fd5b615964878286016157f3565b60608301525060808301358281111561597c57600080fd5b6159888782860161584e565b60808301525060a0830135828111156159a057600080fd5b6159ac8782860161584e565b60a08301525095945050505050565b61ffff818116838216019080821115613b8157613b81614f9a565b808202811582820484141761224c5761224c614f9a565b8181038181111561224c5761224c614f9a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615a3e57615a3e615a00565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615a7660808301846145cb565b9695505050505050565b6bffffffffffffffffffffffff828116828216039080821115613b8157613b81614f9a565b60006bffffffffffffffffffffffff80841680615ac457615ac4615a00565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615af857615af8614f9a565b505092915050565b805169ffffffffffffffffffff8116811461478157600080fd5b600080600080600060a08688031215615b3257600080fd5b615b3b86615b00565b9450602086015193506040860151925060608601519150615b5e60808701615b00565b90509295509295909350565b6fffffffffffffffffffffffffffffffff818116838216019080821115613b8157613b81614f9a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215615bd457600080fd5b6040516040810181811067ffffffffffffffff82111715615bf757615bf7614642565b6040528251615c058161480b565b81526020928301519281019290925250919050565b600060a08284031215615c2c57600080fd5b615c3461469b565b82518152602083015160208201526040830151615c508161480b565b60408201526060830151615c638161480b565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", + 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\":\"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\":\"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\":\"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: "0x6101806040523480156200001257600080fd5b50604051620064ff380380620064ff83398101604081905262000035916200062f565b80816001600160a01b031663ca30e6036040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000075573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200009b91906200062f565b826001600160a01b031663226cf83c6040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200010091906200062f565b836001600160a01b031663614486af6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200013f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200016591906200062f565b846001600160a01b0316636709d0e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015620001a4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001ca91906200062f565b856001600160a01b0316635425d8ac6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000209573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200022f91906200062f565b866001600160a01b031663a08714c06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200026e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200029491906200062f565b876001600160a01b031663c5b964e06040518163ffffffff1660e01b8152600401602060405180830381865afa158015620002d3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620002f9919062000656565b886001600160a01b031663ac4dc59a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000338573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200035e91906200062f565b3380600081620003b55760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620003e857620003e8816200056b565b5050506001600160a01b0380891660805287811660a05286811660c05285811660e052848116610100528316610120526025805483919060ff19166001838181111562000439576200043962000679565b0217905550806001600160a01b0316610140816001600160a01b03168152505060c0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200049a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620004c091906200068f565b60ff1660a0516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000504573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200052a91906200068f565b60ff16146200054c576040516301f86e1760e41b815260040160405180910390fd5b5050506001600160a01b039095166101605250620006b4945050505050565b336001600160a01b03821603620005c55760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401620003ac565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b03811681146200062c57600080fd5b50565b6000602082840312156200064257600080fd5b81516200064f8162000616565b9392505050565b6000602082840312156200066957600080fd5b8151600281106200064f57600080fd5b634e487b7160e01b600052602160045260246000fd5b600060208284031215620006a257600080fd5b815160ff811681146200064f57600080fd5b60805160a05160c05160e05161010051610120516101405161016051615dc8620007376000396000818160c9015261017c015260005050600061226a015260005050600050506000613a2801526000505060008181610df301528181610f010152818161102c015281816110760152818161176f015261336e0152615dc86000f3fe6080604052600436106100c75760003560e01c8063a4c0ed3611610074578063b1dc65a41161004e578063b1dc65a414610338578063e3d0e71214610358578063f2fde38b14610378576100c7565b8063a4c0ed361461029b578063aed2e929146102bb578063afcb95d7146102f2576100c7565b80637bee169d116100a55780637bee169d146101d657806381ff7048146101f65780638da5cb5b14610270576100c7565b8063181f5a771461010e578063349e8cca1461016d57806379ba5097146101c1575b7f00000000000000000000000000000000000000000000000000000000000000003660008037600080366000845af43d6000803e808015610107573d6000f35b3d6000fd5b005b34801561011a57600080fd5b506101576040518060400160405280601881526020017f4175746f6d6174696f6e526567697374727920322e332e30000000000000000081525081565b604051610164919061476f565b60405180910390f35b34801561017957600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610164565b3480156101cd57600080fd5b5061010c610398565b3480156101e257600080fd5b5061010c6101f1366004614ce4565b61049a565b34801561020257600080fd5b5061024d60175460135463ffffffff74010000000000000000000000000000000000000000830481169378010000000000000000000000000000000000000000000000009093041691565b6040805163ffffffff948516815293909216602084015290820152606001610164565b34801561027c57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff1661019c565b3480156102a757600080fd5b5061010c6102b6366004614e45565b610ddb565b3480156102c757600080fd5b506102db6102d6366004614ea1565b6110f7565b604080519215158352602083019190915201610164565b3480156102fe57600080fd5b50601354601454604080516000815260208101939093526c0100000000000000000000000090910463ffffffff1690820152606001610164565b34801561034457600080fd5b5061010c610353366004614f32565b6112a2565b34801561036457600080fd5b5061010c610373366004614fe9565b611583565b34801561038457600080fd5b5061010c6103933660046150b6565b6115bd565b60015473ffffffffffffffffffffffffffffffffffffffff16331461041e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b6104a26115d1565b601f885111156104de576040517f25d0209c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8560ff1660000361051b576040517fe77dba5600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8651885114158061053a5750610532866003615109565b60ff16885111155b15610571576040517f1d2d1c5800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80518251146105ac576040517fcf54c06a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6105b68282611654565b6105c08888611abc565b604051806101200160405280601460000160009054906101000a90046bffffffffffffffffffffffff166bffffffffffffffffffffffff168152602001600063ffffffff1681526020018660a0015162ffffff16815260200186610120015161ffff1681526020018760ff168152602001601460000160169054906101000a900460ff1615158152602001601460000160179054906101000a900460ff1615158152602001866080015115158152602001866101e0015173ffffffffffffffffffffffffffffffffffffffff16815250601460008201518160000160006101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff160217905550602082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160106101000a81548162ffffff021916908362ffffff16021790555060608201518160000160136101000a81548161ffff021916908361ffff16021790555060808201518160000160156101000a81548160ff021916908360ff16021790555060a08201518160000160166101000a81548160ff02191690831515021790555060c08201518160000160176101000a81548160ff02191690831515021790555060e08201518160000160186101000a81548160ff0219169083151502179055506101008201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550905050604051806101600160405280866060015173ffffffffffffffffffffffffffffffffffffffff168152602001866000015163ffffffff168152602001866020015163ffffffff1681526020016016600001601c9054906101000a900463ffffffff1663ffffffff16815260200186610100015173ffffffffffffffffffffffffffffffffffffffff168152602001601660010160149054906101000a900463ffffffff1663ffffffff168152602001601660010160189054906101000a900463ffffffff1663ffffffff168152602001866040015163ffffffff16815260200186610140015173ffffffffffffffffffffffffffffffffffffffff1681526020018660c0015163ffffffff1681526020018660e0015163ffffffff16815250601660008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548163ffffffff021916908363ffffffff160217905550606082015181600001601c6101000a81548163ffffffff021916908363ffffffff16021790555060808201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160010160146101000a81548163ffffffff021916908363ffffffff16021790555060c08201518160010160186101000a81548163ffffffff021916908363ffffffff16021790555060e082015181600101601c6101000a81548163ffffffff021916908363ffffffff1602179055506101008201518160020160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506101208201518160020160146101000a81548163ffffffff021916908363ffffffff1602179055506101408201518160020160186101000a81548163ffffffff021916908363ffffffff160217905550905050846101600151601981905550846101800151601a81905550846101a00151601b819055506000601660010160189054906101000a900463ffffffff169050856101e0015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bc6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bea9190615125565b601780547fffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffff16780100000000000000000000000000000000000000000000000063ffffffff9384160217808255600192601491610c619185917401000000000000000000000000000000000000000090041661513e565b92506101000a81548163ffffffff021916908363ffffffff160217905550600086604051602001610c9291906151ac565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052601754909150610cf7904690309074010000000000000000000000000000000000000000900463ffffffff168d8d8d878d8d61217d565b601355600960008181610d0a8282614656565b5050505060005b876101c0015151811015610d6457610d51886101c001518281518110610d3957610d39615332565b6020026020010151600961222790919063ffffffff16565b5080610d5c81615361565b915050610d11565b506013546017546040517f1591690b8638f5fb2dbec82ac741805ac5da8b45dc5263f4875b0496fdce4e0592610dc79286927401000000000000000000000000000000000000000090910463ffffffff16908f908f908f9089908f908f90615399565b60405180910390a150505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610e4a576040517fc8bad78d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610e84576040517fdfe9309000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610e928284018461542f565b6000818152600460205260409020549091506601000000000000900463ffffffff90811614610eed576040517f9c0083a200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000818152600460205260409020600201547f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff908116911614610f71576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081815260046020526040902060010154610fb090859070010000000000000000000000000000000090046bffffffffffffffffffffffff16615448565b600082815260046020908152604080832060010180546bffffffffffffffffffffffff95909516700100000000000000000000000000000000027fffffffff000000000000000000000000ffffffffffffffffffffffffffffffff9095169490941790935573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016825260219052205461105f90859061546d565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660009081526021602090815260409182902093909355516bffffffffffffffffffffffff871681529087169183917fafd24114486da8ebfc32f3626dada8863652e187461aa74d4bfa734891506203910160405180910390a35050505050565b600080611102612252565b601454760100000000000000000000000000000000000000000000900460ff1615611159576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600085815260046020908152604091829020825161012081018452815460ff8082161515835261010080830490911615158386015262010000820463ffffffff90811684880181905266010000000000008404821660608601526a010000000000000000000090930473ffffffffffffffffffffffffffffffffffffffff9081166080860181905260018701546fffffffffffffffffffffffffffffffff811660a088015270010000000000000000000000000000000081046bffffffffffffffffffffffff1660c08801527c0100000000000000000000000000000000000000000000000000000000900490921660e0860152600290950154909416908301528451601f890185900485028101850190955287855290936112959389908990819084018382808284376000920191909152506122c192505050565b9097909650945050505050565b60005a60408051610120810182526014546bffffffffffffffffffffffff8116825263ffffffff6c01000000000000000000000000820416602083015262ffffff7001000000000000000000000000000000008204169282019290925261ffff730100000000000000000000000000000000000000830416606082015260ff75010000000000000000000000000000000000000000008304811660808301527601000000000000000000000000000000000000000000008304811615801560a08401527701000000000000000000000000000000000000000000000084048216151560c0840152780100000000000000000000000000000000000000000000000090930416151560e082015260155473ffffffffffffffffffffffffffffffffffffffff16610100820152919250611406576040517f24522f3400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b336000908152600b602052604090205460ff1661144f576040517f1099ed7500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6013548a351461148b576040517fdfdcf8e700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b608081015161149b906001615480565b60ff16861415806114ac5750858414155b156114e3576040517f0244f71a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6114f38a8a8a8a8a8a8a8a6124dc565b60006114ff8a8a612745565b905060208b0135600881901c63ffffffff1661151c8484876127fe565b836020015163ffffffff168163ffffffff16111561157457601480547fffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffff166c0100000000000000000000000063ffffffff8416021790555b50505050505050505050505050565b60008060008580602001905181019061159c9190615657565b9250925092506115b2898989868989888861049a565b505050505050505050565b6115c56115d1565b6115ce816133e4565b50565b60005473ffffffffffffffffffffffffffffffffffffffff163314611652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610415565b565b60005b60245481101561171257602260006024838154811061167857611678615332565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff168352820192909252604001812080547fffffffffff000000000000000000000000000000000000000000000000000000168155600181019190915560020180547fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001690558061170a81615361565b915050611657565b5061171f60246000614656565b60255460ff1660005b8351811015611ab657600084828151811061174557611745615332565b60200260200101519050600084838151811061176357611763615332565b602002602001015190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161480156117d9575060018460018111156117d7576117d7615802565b145b15611810576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8216158061184b5750604081015173ffffffffffffffffffffffffffffffffffffffff16155b15611882576040517f8579befe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff828116600090815260226020526040902054670100000000000000900416156118ec576040517f357d0cc400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6024805460018082019092557f7cd332d19b93bcabe3cce7ca0c18a052f57e5fd03b4758a09f30f5ddc4b22ec40180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff8581169182179092556000818152602260209081526040918290208651815488840180518a8701805163ffffffff9095167fffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000909416841764010000000062ffffff93841602177fffffffffff0000000000000000000000000000000000000000ffffffffffffff16670100000000000000958b16959095029490941785556060808c0180519b87019b909b556080808d018051600290980180547fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166bffffffffffffffffffffffff998a1617905589519586529351909216968401969096529251909716948101949094529551918301919091529251909216928201929092527f720a5849025dc4fd0061aed1bb30efd713cde64ce7f8d807953ecca27c8f143c9060a00160405180910390a250508080611aae90615361565b915050611728565b50505050565b60005b600e54811015611b3357611b20600e8281548110611adf57611adf615332565b600091825260209091200154601454600e5473ffffffffffffffffffffffffffffffffffffffff909216916bffffffffffffffffffffffff909116906134d9565b5080611b2b81615361565b915050611abf565b5060255460009060ff16815b600e54811015611ca457600e8181548110611b5c57611b5c615332565b6000918252602082200154600d805473ffffffffffffffffffffffffffffffffffffffff9092169550600c929184908110611b9957611b99615332565b600091825260208083209091015473ffffffffffffffffffffffffffffffffffffffff9081168452838201949094526040928301822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00001690559286168152600b909252902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556001826001811115611c3b57611c3b615802565b148015611c80575073ffffffffffffffffffffffffffffffffffffffff83166000908152600b60205260409020546201000090046bffffffffffffffffffffffff1615155b15611c9257611c90600f84612227565b505b80611c9c81615361565b915050611b3f565b50611cb1600d6000614656565b611cbd600e6000614656565b6040805160808101825260008082526020820181905291810182905260608101829052905b855181101561214d57600c6000878381518110611d0157611d01615332565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528101919091526040016000205460ff1615611d6c576040517f77cea0fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16868281518110611d9657611d96615332565b602002602001015173ffffffffffffffffffffffffffffffffffffffff1603611deb576040517f815e1d6400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405180604001604052806001151581526020018260ff16815250600c6000888481518110611e1c57611e1c615332565b60209081029190910181015173ffffffffffffffffffffffffffffffffffffffff1682528181019290925260400160002082518154939092015160ff16610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909316929092171790558451859082908110611ec457611ec4615332565b60200260200101519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611f34576040517f58a70a0a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84166000908152600b60209081526040918290208251608081018452905460ff80821615801584526101008304909116938301939093526bffffffffffffffffffffffff6201000082048116948301949094526e01000000000000000000000000000090049092166060830152909250611fef576040517f6a7281ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600180835260ff80831660208086019182526014546bffffffffffffffffffffffff9081166060880190815273ffffffffffffffffffffffffffffffffffffffff8a166000908152600b909352604092839020885181549551948a0151925184166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff939094166201000002929092167fffffffffffff000000000000000000000000000000000000000000000000ffff94909616610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00009095169490941717919091169290921791909117905583600181111561212957612129615802565b0361213b57612139600f856136e1565b505b8061214581615361565b915050611ce2565b50845161216190600d906020880190614674565b50835161217590600e906020870190614674565b505050505050565b6000808a8a8a8a8a8a8a8a8a6040516020016121a199989796959493929190615831565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905280516020909101207dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167e01000000000000000000000000000000000000000000000000000000000000179b9a5050505050505050505050565b60006122498373ffffffffffffffffffffffffffffffffffffffff8416613703565b90505b92915050565b3273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611652576040517fb60ac5db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601454600090819077010000000000000000000000000000000000000000000000900460ff161561231e576040517f37ed32e800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16770100000000000000000000000000000000000000000000001790556040517f4585e33b000000000000000000000000000000000000000000000000000000009061239390859060240161476f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009094169390931790925290517f79188d1600000000000000000000000000000000000000000000000000000000815290935073ffffffffffffffffffffffffffffffffffffffff8616906379188d169061246690879087906004016158c6565b60408051808303816000875af1158015612484573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a891906158df565b601480547fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff16905590969095509350505050565b600087876040516124ee92919061590d565b604051908190038120612505918b9060200161591d565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201208383019092526000808452908301819052909250906000805b888110156126dc5760018587836020811061257157612571615332565b61257e91901a601b615480565b8c8c8581811061259057612590615332565b905060200201358b8b868181106125a9576125a9615332565b90506020020135604051600081526020016040526040516125e6949392919093845260ff9290921660208401526040830152606082015260800190565b6020604051602081039080840390855afa158015612608573d6000803e3d6000fd5b5050604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081015173ffffffffffffffffffffffffffffffffffffffff81166000908152600c602090815290849020838501909452925460ff80821615158085526101009092041693830193909352909550935090506126b6576040517f0f4c073700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b826020015160080260ff166001901b8401935080806126d490615361565b915050612554565b50827e01010101010101010101010101010101010101010101010101010101010101841614612737576040517fc103be2e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050505050505050565b61277e6040518060c001604052806000815260200160008152602001606081526020016060815260200160608152602001606081525090565b600061278c83850185615a0e565b60408101515160608201515191925090811415806127af57508082608001515114155b806127bf5750808260a001515114155b156127f6576040517fb55ac75400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b509392505050565b600082604001515167ffffffffffffffff81111561281e5761281e614782565b6040519080825280602002602001820160405280156128ea57816020015b6040805161020081018252600060e08201818152610100830182905261012083018290526101408301829052610160830182905261018083018290526101a083018290526101c083018290526101e0830182905282526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90920191018161283c5790505b50905060006040518060800160405280600061ffff16815260200160006bffffffffffffffffffffffff16815260200160006bffffffffffffffffffffffff16815260200160008152509050600085610100015173ffffffffffffffffffffffffffffffffffffffff166357e871e76040518163ffffffff1660e01b8152600401602060405180830381865afa158015612988573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129ac9190615125565b9050600086610100015173ffffffffffffffffffffffffffffffffffffffff166318b8f6136040518163ffffffff1660e01b8152600401602060405180830381865afa158015612a00573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a249190615125565b905060005b866040015151811015612eb4576004600088604001518381518110612a5057612a50615332565b6020908102919091018101518252818101929092526040908101600020815161012081018352815460ff8082161515835261010080830490911615159583019590955263ffffffff620100008204811694830194909452660100000000000081048416606083015273ffffffffffffffffffffffffffffffffffffffff6a01000000000000000000009091048116608083015260018301546fffffffffffffffffffffffffffffffff811660a08401526bffffffffffffffffffffffff70010000000000000000000000000000000082041660c08401527c0100000000000000000000000000000000000000000000000000000000900490931660e0820152600290910154909116918101919091528551869083908110612b7357612b73615332565b602002602001015160000181905250612ba887604001518281518110612b9b57612b9b615332565b6020026020010151613752565b858281518110612bba57612bba615332565b6020026020010151606001906001811115612bd757612bd7615802565b90816001811115612bea57612bea615802565b81525050612c4e87604001518281518110612c0757612c07615332565b60200260200101518489608001518481518110612c2657612c26615332565b6020026020010151888581518110612c4057612c40615332565b60200260200101518c6137fd565b868381518110612c6057612c60615332565b6020026020010151602001878481518110612c7d57612c7d615332565b602002602001015160c0018281525082151515158152505050848181518110612ca857612ca8615332565b60200260200101516020015115612cd857600184600001818151612ccc9190615afb565b61ffff16905250612cdd565b612ea2565b612d43858281518110612cf257612cf2615332565b6020026020010151600001516080015188606001518381518110612d1857612d18615332565b60200260200101518960a001518481518110612d3657612d36615332565b60200260200101516122c1565b868381518110612d5557612d55615332565b6020026020010151604001878481518110612d7257612d72615332565b6020026020010151608001828152508215151515815250505087608001516001612d9c9190615480565b612daa9060ff166040615b16565b6103a48860a001518381518110612dc357612dc3615332565b602002602001015151612dd6919061546d565b612de0919061546d565b858281518110612df257612df2615332565b602002602001015160a0018181525050848181518110612e1457612e14615332565b602002602001015160a0015184606001818151612e31919061546d565b9052508451859082908110612e4857612e48615332565b60200260200101516080015186612e5f9190615b2d565b9550612ea287604001518281518110612e7a57612e7a615332565b602002602001015184878481518110612e9557612e95615332565b602002602001015161391c565b80612eac81615361565b915050612a29565b50825161ffff16600003612ecb5750505050505050565b6155f0612ed9366010615b16565b5a612ee49088615b2d565b612eee919061546d565b612ef8919061546d565b8351909550611b5890612f0f9061ffff1687615b6f565b612f19919061546d565b60408051606081018252600080825260208201819052918101829052919650612f4189613a21565b905060005b88604001515181101561327d57868181518110612f6557612f65615332565b6020026020010151602001511561326b57801580612ffd575086612f8a600183615b2d565b81518110612f9a57612f9a615332565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff16878281518110612fd357612fd3615332565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff1614155b156130315761302e8a88838151811061301857613018615332565b6020026020010151600001516101000151613b12565b92505b600061314f8b6040518061012001604052808b868151811061305557613055615332565b60200260200101516080015181526020018c81526020018a606001518c878151811061308357613083615332565b602002602001015160a001518a61309a9190615b16565b6130a49190615b6f565b81526020018d6000015181526020018d6020015181526020018681526020018b86815181106130d5576130d5615332565b602002602001015160000151610100015173ffffffffffffffffffffffffffffffffffffffff168152602001878152602001600115158152508c60400151858151811061312457613124615332565b60200260200101518b868151811061313e5761313e615332565b602002602001015160000151613c63565b90508060600151876040018181516131679190615448565b6bffffffffffffffffffffffff16905250604081015160208801805161318e908390615448565b6bffffffffffffffffffffffff1690525087518890839081106131b3576131b3615332565b60200260200101516040015115158a6040015183815181106131d7576131d7615332565b60200260200101517fad8cc9579b21dfe2c2f6ea35ba15b656e46b4f5b0cb424f52739b8ce5cac9c5b836060015184604001516132149190615448565b8b868151811061322657613226615332565b6020026020010151608001518d8f60800151888151811061324957613249615332565b60200260200101516040516132619493929190615b83565b60405180910390a3505b8061327581615361565b915050612f46565b505050602083810151336000908152600b909252604090912080546002906132ba9084906201000090046bffffffffffffffffffffffff16615448565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151601460000160008282829054906101000a90046bffffffffffffffffffffffff166133189190615448565b92506101000a8154816bffffffffffffffffffffffff02191690836bffffffffffffffffffffffff1602179055508260400151836020015161335a9190615448565b6bffffffffffffffffffffffff16602160007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546133d6919061546d565b909155505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff821603613463576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610415565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600b602090815260408083208151608081018352905460ff80821615801584526101008304909116948301949094526bffffffffffffffffffffffff6201000082048116938301939093526e01000000000000000000000000000090049091166060820152906136d55760008160600151856135719190615bc0565b9050600061357f8583615be5565b905080836040018181516135939190615448565b6bffffffffffffffffffffffff169052506135ae8582615c10565b836060018181516135bf9190615448565b6bffffffffffffffffffffffff90811690915273ffffffffffffffffffffffffffffffffffffffff89166000908152600b602090815260409182902087518154928901519389015160608a015186166e010000000000000000000000000000027fffffffffffff000000000000000000000000ffffffffffffffffffffffffffff919096166201000002167fffffffffffff000000000000000000000000000000000000000000000000ffff60ff95909516610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171792909216179190911790555050505b60400151949350505050565b60006122498373ffffffffffffffffffffffffffffffffffffffff8416613f5f565b600081815260018301602052604081205461374a5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561224c565b50600061224c565b6000818160045b600f8110156137df577fff00000000000000000000000000000000000000000000000000000000000000821683826020811061379757613797615332565b1a60f81b7effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916146137cd57506000949350505050565b806137d781615361565b915050613759565b5081600f1a60018111156137f5576137f5615802565b949350505050565b60008080808560600151600181111561381857613818615802565b0361383e5761382a8888888888614052565b61383957600092509050613912565b6138b6565b60018560600151600181111561385657613856615802565b03613884576000613869898989886141dc565b925090508061387e5750600092509050613912565b506138b6565b6040517ff2b2d41200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84516060015163ffffffff16871061390b57877fc3237c8807c467c1b39b8d0395eff077313e691bf0a7388106792564ebfd5636876040516138f8919061476f565b60405180910390a2600092509050613912565b6001925090505b9550959350505050565b60008160600151600181111561393457613934615802565b0361399857600083815260046020526040902060010180547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c010000000000000000000000000000000000000000000000000000000063ffffffff851602179055505050565b6001816060015160018111156139b0576139b0615802565b03613a1c5760c08101805160009081526008602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055915191517fa4a4e334c0e330143f9437484fe516c13bc560b86b5b0daf58e7084aaac228f29190a25b505050565b60008060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa158015613a91573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ab59190615c5a565b50935050925050600082131580613acb57508042105b80613afb57506000846040015162ffffff16118015613afb5750613aef8142615b2d565b846040015162ffffff16105b15613b0b575050601b5492915050565b5092915050565b604080516060810182526000808252602080830182815283850183905273ffffffffffffffffffffffffffffffffffffffff868116845260229092528483208054640100000000810462ffffff1690925263ffffffff8216855285517ffeaf968c00000000000000000000000000000000000000000000000000000000815295519495909484936701000000000000009093049092169163feaf968c9160048082019260a0929091908290030181865afa158015613bd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613bf89190615c5a565b50935050925050600082131580613c0e57508042105b80613c3e57506000866040015162ffffff16118015613c3e5750613c328142615b2d565b866040015162ffffff16105b15613c525760018301546040850152613c5a565b604084018290525b50505092915050565b604080516080810182526000808252602080830182905292820181905260608201529082015115613cdc5760008381526023602090815260409182902082518084019093525463ffffffff811680845262ffffff640100000000909204821693830193845260e088018051919091529251925192169101525b6000613ce886866143e9565b60c0840151602082015182519293509091600091613d0591615448565b905082600001516bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613d8a57819050613d6b87608001518860e0015160400151846bffffffffffffffffffffffff16613d5c9190615b16565b613d669190615b6f565b6145b4565b6bffffffffffffffffffffffff16604084015260006060840152613e16565b806bffffffffffffffffffffffff16826bffffffffffffffffffffffff161015613e1657819050613e0283604001516bffffffffffffffffffffffff1688608001518960e0015160400151856bffffffffffffffffffffffff16613dee9190615b16565b613df89190615b6f565b613d669190615b2d565b6bffffffffffffffffffffffff1660608401525b60008681526004602052604090206001018054829190601090613e5c90849070010000000000000000000000000000000090046bffffffffffffffffffffffff16615bc0565b82546101009290920a6bffffffffffffffffffffffff81810219909316918316021790915560008881526004602052604081206001018054928516935091613eb79084906fffffffffffffffffffffffffffffffff16615caa565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806bffffffffffffffffffffffff16602160008960c0015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254613f4e9190615b2d565b909155509298975050505050505050565b60008181526001830160205260408120548015614048576000613f83600183615b2d565b8554909150600090613f9790600190615b2d565b9050818114613ffc576000866000018281548110613fb757613fb7615332565b9060005260206000200154905080876000018481548110613fda57613fda615332565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061400d5761400d615cd3565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061224c565b600091505061224c565b600080848060200190518101906140699190615d02565b845160e00151815191925063ffffffff908116911610156140c657867f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e8866040516140b4919061476f565b60405180910390a260009150506141d3565b8260e00151801561418657506020810151158015906141865750602081015161010084015182516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561415f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141839190615125565b14155b806141985750805163ffffffff168611155b156141cd57867f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc301866040516140b4919061476f565b60019150505b95945050505050565b6000806000848060200190518101906141f59190615d5a565b905060008782600001518360200151846040015160405160200161425794939291909384526020840192909252604083015260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016606082015260640190565b6040516020818303038152906040528051906020012090508460e00151801561433257506080820151158015906143325750608082015161010086015160608401516040517f85df51fd00000000000000000000000000000000000000000000000000000000815263ffffffff909116600482015273ffffffffffffffffffffffffffffffffffffffff909116906385df51fd90602401602060405180830381865afa15801561430b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061432f9190615125565b14155b80614347575086826060015163ffffffff1610155b1561439157877f6aa7f60c176da7af894b384daea2249497448137f5943c1237ada8bc92bdc3018760405161437c919061476f565b60405180910390a26000935091506143e09050565b60008181526008602052604090205460ff16156143d857877f405288ea7be309e16cfdf481367f90a413e1d4634fcdaf8966546db9b93012e88760405161437c919061476f565b600193509150505b94509492505050565b6040805160808101825260008082526020820181905291810182905260608101919091526000836060015161ffff1683606001516144279190615b16565b9050826101000151801561443a5750803a105b1561444257503a5b60008360a00151846040015185602001518660000151614462919061546d565b61446c9085615b16565b614476919061546d565b6144809190615b16565b90506144998460e001516040015182613d669190615b6f565b6bffffffffffffffffffffffff16835260808401516144bc90613d669083615b6f565b6bffffffffffffffffffffffff16604084015260e0840151602001516000906144f39062ffffff16683635c9adc5dea00000615b16565b9050600081633b9aca008760a001518860e001516000015163ffffffff1689604001518a60000151896145269190615b16565b614530919061546d565b61453a9190615b16565b6145449190615b16565b61454e9190615b6f565b614558919061546d565b90506145718660e001516040015182613d669190615b6f565b6bffffffffffffffffffffffff166020860152608086015161459790613d669083615b6f565b6bffffffffffffffffffffffff1660608601525050505092915050565b60006bffffffffffffffffffffffff821115614652576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201527f36206269747300000000000000000000000000000000000000000000000000006064820152608401610415565b5090565b50805460008255906000526020600020908101906115ce91906146f6565b8280548282559060005260206000209081019282156146ee579160200282015b828111156146ee57825182547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909116178255602090920191600190910190614694565b506146529291505b5b8082111561465257600081556001016146f7565b6000815180845260005b8181101561473157602081850181015186830182015201614715565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000612249602083018461470b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610200810167ffffffffffffffff811182821017156147d5576147d5614782565b60405290565b60405160a0810167ffffffffffffffff811182821017156147d5576147d5614782565b60405160c0810167ffffffffffffffff811182821017156147d5576147d5614782565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561486857614868614782565b604052919050565b600067ffffffffffffffff82111561488a5761488a614782565b5060051b60200190565b73ffffffffffffffffffffffffffffffffffffffff811681146115ce57600080fd5b80356148c181614894565b919050565b600082601f8301126148d757600080fd5b813560206148ec6148e783614870565b614821565b82815260059290921b8401810191818101908684111561490b57600080fd5b8286015b8481101561492f57803561492281614894565b835291830191830161490f565b509695505050505050565b803560ff811681146148c157600080fd5b63ffffffff811681146115ce57600080fd5b80356148c18161494b565b80151581146115ce57600080fd5b80356148c181614968565b62ffffff811681146115ce57600080fd5b80356148c181614981565b61ffff811681146115ce57600080fd5b80356148c18161499d565b600061020082840312156149cb57600080fd5b6149d36147b1565b90506149de8261495d565b81526149ec6020830161495d565b60208201526149fd6040830161495d565b6040820152614a0e606083016148b6565b6060820152614a1f60808301614976565b6080820152614a3060a08301614992565b60a0820152614a4160c0830161495d565b60c0820152614a5260e0830161495d565b60e0820152610100614a658184016148b6565b90820152610120614a778382016149ad565b90820152610140614a898382016148b6565b90820152610160828101359082015261018080830135908201526101a080830135908201526101c08083013567ffffffffffffffff811115614aca57600080fd5b614ad6858286016148c6565b8284015250506101e0614aea8184016148b6565b9082015292915050565b803567ffffffffffffffff811681146148c157600080fd5b600082601f830112614b1d57600080fd5b813567ffffffffffffffff811115614b3757614b37614782565b614b6860207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601614821565b818152846020838601011115614b7d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112614bab57600080fd5b81356020614bbb6148e783614870565b82815260059290921b84018101918181019086841115614bda57600080fd5b8286015b8481101561492f578035614bf181614894565b8352918301918301614bde565b6bffffffffffffffffffffffff811681146115ce57600080fd5b600082601f830112614c2957600080fd5b81356020614c396148e783614870565b82815260a09283028501820192828201919087851115614c5857600080fd5b8387015b85811015614cd75781818a031215614c745760008081fd5b614c7c6147db565b8135614c878161494b565b815281860135614c9681614981565b81870152604082810135614ca981614894565b9082015260608281013590820152608080830135614cc681614bfe565b908201528452928401928101614c5c565b5090979650505050505050565b600080600080600080600080610100898b031215614d0157600080fd5b883567ffffffffffffffff80821115614d1957600080fd5b614d258c838d016148c6565b995060208b0135915080821115614d3b57600080fd5b614d478c838d016148c6565b9850614d5560408c0161493a565b975060608b0135915080821115614d6b57600080fd5b614d778c838d016149b8565b9650614d8560808c01614af4565b955060a08b0135915080821115614d9b57600080fd5b614da78c838d01614b0c565b945060c08b0135915080821115614dbd57600080fd5b614dc98c838d01614b9a565b935060e08b0135915080821115614ddf57600080fd5b50614dec8b828c01614c18565b9150509295985092959890939650565b60008083601f840112614e0e57600080fd5b50813567ffffffffffffffff811115614e2657600080fd5b602083019150836020828501011115614e3e57600080fd5b9250929050565b60008060008060608587031215614e5b57600080fd5b8435614e6681614894565b935060208501359250604085013567ffffffffffffffff811115614e8957600080fd5b614e9587828801614dfc565b95989497509550505050565b600080600060408486031215614eb657600080fd5b83359250602084013567ffffffffffffffff811115614ed457600080fd5b614ee086828701614dfc565b9497909650939450505050565b60008083601f840112614eff57600080fd5b50813567ffffffffffffffff811115614f1757600080fd5b6020830191508360208260051b8501011115614e3e57600080fd5b60008060008060008060008060e0898b031215614f4e57600080fd5b606089018a811115614f5f57600080fd5b8998503567ffffffffffffffff80821115614f7957600080fd5b614f858c838d01614dfc565b909950975060808b0135915080821115614f9e57600080fd5b614faa8c838d01614eed565b909750955060a08b0135915080821115614fc357600080fd5b50614fd08b828c01614eed565b999c989b50969995989497949560c00135949350505050565b60008060008060008060c0878903121561500257600080fd5b863567ffffffffffffffff8082111561501a57600080fd5b6150268a838b016148c6565b9750602089013591508082111561503c57600080fd5b6150488a838b016148c6565b965061505660408a0161493a565b9550606089013591508082111561506c57600080fd5b6150788a838b01614b0c565b945061508660808a01614af4565b935060a089013591508082111561509c57600080fd5b506150a989828a01614b0c565b9150509295509295509295565b6000602082840312156150c857600080fd5b81356150d381614894565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60ff8181168382160290811690818114613b0b57613b0b6150da565b60006020828403121561513757600080fd5b5051919050565b63ffffffff818116838216019080821115613b0b57613b0b6150da565b600081518084526020808501945080840160005b838110156151a157815173ffffffffffffffffffffffffffffffffffffffff168752958201959082019060010161516f565b509495945050505050565b602081526151c360208201835163ffffffff169052565b600060208301516151dc604084018263ffffffff169052565b50604083015163ffffffff8116606084015250606083015173ffffffffffffffffffffffffffffffffffffffff8116608084015250608083015180151560a08401525060a083015162ffffff811660c08401525060c083015163ffffffff811660e08401525060e083015161010061525b8185018363ffffffff169052565b84015190506101206152848482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151905061014061529b8482018361ffff169052565b84015190506101606152c48482018373ffffffffffffffffffffffffffffffffffffffff169052565b840151610180848101919091528401516101a0808501919091528401516101c0808501919091528401516102006101e08086018290529192509061530c61022086018461515b565b95015173ffffffffffffffffffffffffffffffffffffffff169301929092525090919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615392576153926150da565b5060010190565b600061012063ffffffff808d1684528b6020850152808b166040850152508060608401526153c98184018a61515b565b905082810360808401526153dd818961515b565b905060ff871660a084015282810360c08401526153fa818761470b565b905067ffffffffffffffff851660e084015282810361010084015261541f818561470b565b9c9b505050505050505050505050565b60006020828403121561544157600080fd5b5035919050565b6bffffffffffffffffffffffff818116838216019080821115613b0b57613b0b6150da565b8082018082111561224c5761224c6150da565b60ff818116838216019081111561224c5761224c6150da565b80516148c18161494b565b80516148c181614894565b80516148c181614968565b80516148c181614981565b80516148c18161499d565b600082601f8301126154e157600080fd5b815160206154f16148e783614870565b82815260059290921b8401810191818101908684111561551057600080fd5b8286015b8481101561492f57805161552781614894565b8352918301918301615514565b600082601f83011261554557600080fd5b815160206155556148e783614870565b82815260059290921b8401810191818101908684111561557457600080fd5b8286015b8481101561492f57805161558b81614894565b8352918301918301615578565b600082601f8301126155a957600080fd5b815160206155b96148e783614870565b82815260a092830285018201928282019190878511156155d857600080fd5b8387015b85811015614cd75781818a0312156155f45760008081fd5b6155fc6147db565b81516156078161494b565b81528186015161561681614981565b8187015260408281015161562981614894565b908201526060828101519082015260808083015161564681614bfe565b9082015284529284019281016155dc565b60008060006060848603121561566c57600080fd5b835167ffffffffffffffff8082111561568457600080fd5b90850190610200828803121561569957600080fd5b6156a16147b1565b6156aa83615499565b81526156b860208401615499565b60208201526156c960408401615499565b60408201526156da606084016154a4565b60608201526156eb608084016154af565b60808201526156fc60a084016154ba565b60a082015261570d60c08401615499565b60c082015261571e60e08401615499565b60e08201526101006157318185016154a4565b908201526101206157438482016154c5565b908201526101406157558482016154a4565b90820152610160838101519082015261018080840151908201526101a080840151908201526101c0808401518381111561578e57600080fd5b61579a8a8287016154d0565b8284015250506101e06157ae8185016154a4565b9082015260208701519095509150808211156157c957600080fd5b6157d587838801615534565b935060408601519150808211156157eb57600080fd5b506157f886828701615598565b9150509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006101208b835273ffffffffffffffffffffffffffffffffffffffff8b16602084015267ffffffffffffffff808b1660408501528160608501526158788285018b61515b565b9150838203608085015261588c828a61515b565b915060ff881660a085015283820360c08501526158a9828861470b565b90861660e0850152838103610100850152905061541f818561470b565b8281526040602082015260006137f5604083018461470b565b600080604083850312156158f257600080fd5b82516158fd81614968565b6020939093015192949293505050565b8183823760009101908152919050565b8281526080810160608360208401379392505050565b600082601f83011261594457600080fd5b813560206159546148e783614870565b82815260059290921b8401810191818101908684111561597357600080fd5b8286015b8481101561492f5780358352918301918301615977565b600082601f83011261599f57600080fd5b813560206159af6148e783614870565b82815260059290921b840181019181810190868411156159ce57600080fd5b8286015b8481101561492f57803567ffffffffffffffff8111156159f25760008081fd5b615a008986838b0101614b0c565b8452509183019183016159d2565b600060208284031215615a2057600080fd5b813567ffffffffffffffff80821115615a3857600080fd5b9083019060c08286031215615a4c57600080fd5b615a546147fe565b8235815260208301356020820152604083013582811115615a7457600080fd5b615a8087828601615933565b604083015250606083013582811115615a9857600080fd5b615aa487828601615933565b606083015250608083013582811115615abc57600080fd5b615ac88782860161598e565b60808301525060a083013582811115615ae057600080fd5b615aec8782860161598e565b60a08301525095945050505050565b61ffff818116838216019080821115613b0b57613b0b6150da565b808202811582820484141761224c5761224c6150da565b8181038181111561224c5761224c6150da565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082615b7e57615b7e615b40565b500490565b6bffffffffffffffffffffffff85168152836020820152826040820152608060608201526000615bb6608083018461470b565b9695505050505050565b6bffffffffffffffffffffffff828116828216039080821115613b0b57613b0b6150da565b60006bffffffffffffffffffffffff80841680615c0457615c04615b40565b92169190910492915050565b6bffffffffffffffffffffffff818116838216028082169190828114615c3857615c386150da565b505092915050565b805169ffffffffffffffffffff811681146148c157600080fd5b600080600080600060a08688031215615c7257600080fd5b615c7b86615c40565b9450602086015193506040860151925060608601519150615c9e60808701615c40565b90509295509295909350565b6fffffffffffffffffffffffffffffffff818116838216019080821115613b0b57613b0b6150da565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b600060408284031215615d1457600080fd5b6040516040810181811067ffffffffffffffff82111715615d3757615d37614782565b6040528251615d458161494b565b81526020928301519281019290925250919050565b600060a08284031215615d6c57600080fd5b615d746147db565b82518152602083015160208201526040830151615d908161494b565b60408201526060830151615da38161494b565b6060820152608092830151928101929092525091905056fea164736f6c6343000813000a", } var AutomationRegistryABI = AutomationRegistryMetaData.ABI @@ -1496,42 +1496,42 @@ func (it *AutomationRegistryFeesWithdrawnIterator) Close() error { } type AutomationRegistryFeesWithdrawn struct { - Recipient common.Address AssetAddress common.Address + Recipient common.Address Amount *big.Int Raw types.Log } -func (_AutomationRegistry *AutomationRegistryFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryFeesWithdrawnIterator, error) { +func (_AutomationRegistry *AutomationRegistryFilterer) FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryFeesWithdrawnIterator, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistry.contract.FilterLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistry.contract.FilterLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } return &AutomationRegistryFeesWithdrawnIterator{contract: _AutomationRegistry.contract, event: "FeesWithdrawn", logs: logs, sub: sub}, nil } -func (_AutomationRegistry *AutomationRegistryFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) { +func (_AutomationRegistry *AutomationRegistryFilterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _AutomationRegistry.contract.WatchLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _AutomationRegistry.contract.WatchLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } @@ -5695,9 +5695,9 @@ type AutomationRegistryInterface interface { ParseDedupKeyAdded(log types.Log) (*AutomationRegistryDedupKeyAdded, error) - FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*AutomationRegistryFeesWithdrawnIterator, error) + FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*AutomationRegistryFeesWithdrawnIterator, error) - WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryFeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) + WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *AutomationRegistryFeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) ParseFeesWithdrawn(log types.Log) (*AutomationRegistryFeesWithdrawn, error) 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 552d2f91c3f..8db1a62050c 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 @@ -133,7 +133,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\":\"int256\",\"name\":\"available\",\"type\":\"int256\"},{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"}],\"name\":\"InsufficientBalance\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidBillingToken\",\"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\":\"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\":\"recipient\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"assetAddress\",\"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\":\"upkeepTranscoderVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"upkeepVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"assetAddress\",\"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\":\"withdrawLinkFees\",\"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\":\"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\":\"upkeepTranscoderVersion\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"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 @@ -1940,16 +1940,16 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession return _IAutomationRegistryMaster23.Contract.UnpauseUpkeep(&_IAutomationRegistryMaster23.TransactOpts, id) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawERC20Fees(opts *bind.TransactOpts, assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.contract.Transact(opts, "withdrawERC20Fees", assetAddress, to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawERC20Fees(opts *bind.TransactOpts, asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.contract.Transact(opts, "withdrawERC20Fees", asset, to, amount) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) WithdrawERC20Fees(assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.Contract.WithdrawERC20Fees(&_IAutomationRegistryMaster23.TransactOpts, assetAddress, to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) WithdrawERC20Fees(asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.Contract.WithdrawERC20Fees(&_IAutomationRegistryMaster23.TransactOpts, asset, to, amount) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession) WithdrawERC20Fees(assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.Contract.WithdrawERC20Fees(&_IAutomationRegistryMaster23.TransactOpts, assetAddress, to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession) WithdrawERC20Fees(asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.Contract.WithdrawERC20Fees(&_IAutomationRegistryMaster23.TransactOpts, asset, to, amount) } func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) { @@ -1964,16 +1964,16 @@ func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession return _IAutomationRegistryMaster23.Contract.WithdrawFunds(&_IAutomationRegistryMaster23.TransactOpts, id, to) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawLinkFees(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.contract.Transact(opts, "withdrawLinkFees", to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawLink(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.contract.Transact(opts, "withdrawLink", to, amount) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) WithdrawLinkFees(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.Contract.WithdrawLinkFees(&_IAutomationRegistryMaster23.TransactOpts, to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Session) WithdrawLink(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.Contract.WithdrawLink(&_IAutomationRegistryMaster23.TransactOpts, to, amount) } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession) WithdrawLinkFees(to common.Address, amount *big.Int) (*types.Transaction, error) { - return _IAutomationRegistryMaster23.Contract.WithdrawLinkFees(&_IAutomationRegistryMaster23.TransactOpts, to, amount) +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23TransactorSession) WithdrawLink(to common.Address, amount *big.Int) (*types.Transaction, error) { + return _IAutomationRegistryMaster23.Contract.WithdrawLink(&_IAutomationRegistryMaster23.TransactOpts, to, amount) } func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Transactor) WithdrawPayment(opts *bind.TransactOpts, from common.Address, to common.Address) (*types.Transaction, error) { @@ -3069,42 +3069,42 @@ func (it *IAutomationRegistryMaster23FeesWithdrawnIterator) Close() error { } type IAutomationRegistryMaster23FeesWithdrawn struct { - Recipient common.Address AssetAddress common.Address + Recipient common.Address Amount *big.Int Raw types.Log } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Filterer) FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*IAutomationRegistryMaster23FeesWithdrawnIterator, error) { +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Filterer) FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*IAutomationRegistryMaster23FeesWithdrawnIterator, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _IAutomationRegistryMaster23.contract.FilterLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _IAutomationRegistryMaster23.contract.FilterLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } return &IAutomationRegistryMaster23FeesWithdrawnIterator{contract: _IAutomationRegistryMaster23.contract, event: "FeesWithdrawn", logs: logs, sub: sub}, nil } -func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Filterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *IAutomationRegistryMaster23FeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) { +func (_IAutomationRegistryMaster23 *IAutomationRegistryMaster23Filterer) WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *IAutomationRegistryMaster23FeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) { - var recipientRule []interface{} - for _, recipientItem := range recipient { - recipientRule = append(recipientRule, recipientItem) - } var assetAddressRule []interface{} for _, assetAddressItem := range assetAddress { assetAddressRule = append(assetAddressRule, assetAddressItem) } + var recipientRule []interface{} + for _, recipientItem := range recipient { + recipientRule = append(recipientRule, recipientItem) + } - logs, sub, err := _IAutomationRegistryMaster23.contract.WatchLogs(opts, "FeesWithdrawn", recipientRule, assetAddressRule) + logs, sub, err := _IAutomationRegistryMaster23.contract.WatchLogs(opts, "FeesWithdrawn", assetAddressRule, recipientRule) if err != nil { return nil, err } @@ -7428,11 +7428,11 @@ type IAutomationRegistryMaster23Interface interface { UnpauseUpkeep(opts *bind.TransactOpts, id *big.Int) (*types.Transaction, error) - WithdrawERC20Fees(opts *bind.TransactOpts, assetAddress common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) + WithdrawERC20Fees(opts *bind.TransactOpts, asset common.Address, to common.Address, amount *big.Int) (*types.Transaction, error) WithdrawFunds(opts *bind.TransactOpts, id *big.Int, to common.Address) (*types.Transaction, error) - WithdrawLinkFees(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) + WithdrawLink(opts *bind.TransactOpts, to common.Address, amount *big.Int) (*types.Transaction, error) WithdrawPayment(opts *bind.TransactOpts, from common.Address, to common.Address) (*types.Transaction, error) @@ -7486,9 +7486,9 @@ type IAutomationRegistryMaster23Interface interface { ParseDedupKeyAdded(log types.Log) (*IAutomationRegistryMaster23DedupKeyAdded, error) - FilterFeesWithdrawn(opts *bind.FilterOpts, recipient []common.Address, assetAddress []common.Address) (*IAutomationRegistryMaster23FeesWithdrawnIterator, error) + FilterFeesWithdrawn(opts *bind.FilterOpts, assetAddress []common.Address, recipient []common.Address) (*IAutomationRegistryMaster23FeesWithdrawnIterator, error) - WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *IAutomationRegistryMaster23FeesWithdrawn, recipient []common.Address, assetAddress []common.Address) (event.Subscription, error) + WatchFeesWithdrawn(opts *bind.WatchOpts, sink chan<- *IAutomationRegistryMaster23FeesWithdrawn, assetAddress []common.Address, recipient []common.Address) (event.Subscription, error) ParseFeesWithdrawn(log types.Log) (*IAutomationRegistryMaster23FeesWithdrawn, error) diff --git a/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go index 1409bcb1548..bfd6644e11e 100644 --- a/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go +++ b/core/gethwrappers/generated/simple_log_upkeep_counter_wrapper/simple_log_upkeep_counter_wrapper.go @@ -34,6 +34,7 @@ type CheckData struct { CheckBurnAmount *big.Int PerformBurnAmount *big.Int EventSig [32]byte + Feeds []string } type Log struct { @@ -48,15 +49,15 @@ type Log struct { } var SimpleLogUpkeepCounterMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timeToPerform\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isRecovered\",\"type\":\"bool\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"checkBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"performBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"eventSig\",\"type\":\"bytes32\"}],\"internalType\":\"structCheckData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"_checkDataConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"dummyMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isRecovered\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeToPerform\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5060006002819055436001556003819055600455610d12806100336000396000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c80637145f11b11610076578063917d895f1161005b578063917d895f1461016b578063c6066f0d14610174578063eb950ce71461017d57600080fd5b80637145f11b1461012f578063806b984f1461016257600080fd5b80634585e33b116100a75780634585e33b1461010057806361bc221a14610115578063697794731461011e57600080fd5b80632cb15864146100c357806340691db4146100df575b600080fd5b6100cc60035481565b6040519081526020015b60405180910390f35b6100f26100ed3660046106c6565b61018a565b6040516100d692919061092d565b61011361010e366004610628565b6102c2565b005b6100cc60045481565b61011361012c36600461066a565b50565b61015261013d36600461060f565b60006020819052908152604090205460ff1681565b60405190151581526020016100d6565b6100cc60015481565b6100cc60025481565b6100cc60055481565b6006546101529060ff1681565b6000606081808061019d8688018861083b565b92509250925060005a905060006101b5600143610c61565b40905060008515610224575b855a6101cd9085610c61565b1015610224578080156101ee575060008281526020819052604090205460ff165b604080516020810185905230918101919091529091506060016040516020818303038152906040528051906020012091506101c1565b8361023260c08d018d610a9d565b600281811061024357610243610ca7565b9050602002013514156102875760018b438c8c60405160200161026994939291906109aa565b604051602081830303815290604052975097505050505050506102ba565b60008b438c8c6040516020016102a094939291906109aa565b604051602081830303815290604052975097505050505050505b935093915050565b6003546102ce57436003555b4360019081556004546102e091610c49565b600455600154600255600080806102f984860186610738565b92509250925082602001514261030f9190610c61565b600555600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556060830151821461037157600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b60008060008380602001905181019061038a9190610867565b92509250925060005a905060006103a2600143610c61565b40905060008415610411575b845a6103ba9085610c61565b1015610411578080156103db575060008281526020819052604090205460ff165b604080516020810185905230918101919091529091506060016040516020818303038152906040528051906020012091506103ae565b600354600154600254600454600554600654604080519687526020870195909552938501929092526060840152608083015260ff16151560a082015232907f29eff4cb37911c3ea85db4630638cc5474fdd0631ec42215aef1d7ec96c8e63d9060c00160405180910390a25050505050505050505050565b803573ffffffffffffffffffffffffffffffffffffffff811681146104ad57600080fd5b919050565b600082601f8301126104c357600080fd5b8135602067ffffffffffffffff8211156104df576104df610cd6565b8160051b6104ee828201610b2f565b83815282810190868401838801850189101561050957600080fd5b600093505b8584101561052c57803583526001939093019291840191840161050e565b50979650505050505050565b60008083601f84011261054a57600080fd5b50813567ffffffffffffffff81111561056257600080fd5b60208301915083602082850101111561057a57600080fd5b9250929050565b600082601f83011261059257600080fd5b813567ffffffffffffffff8111156105ac576105ac610cd6565b6105dd60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601610b2f565b8181528460208386010111156105f257600080fd5b816020850160208301376000918101602001919091529392505050565b60006020828403121561062157600080fd5b5035919050565b6000806020838503121561063b57600080fd5b823567ffffffffffffffff81111561065257600080fd5b61065e85828601610538565b90969095509350505050565b60006060828403121561067c57600080fd5b6040516060810181811067ffffffffffffffff8211171561069f5761069f610cd6565b80604052508235815260208301356020820152604083013560408201528091505092915050565b6000806000604084860312156106db57600080fd5b833567ffffffffffffffff808211156106f357600080fd5b90850190610100828803121561070857600080fd5b9093506020850135908082111561071e57600080fd5b5061072b86828701610538565b9497909650939450505050565b60008060006060848603121561074d57600080fd5b833567ffffffffffffffff8082111561076557600080fd5b90850190610100828803121561077a57600080fd5b610782610b05565b82358152602083013560208201526040830135604082015260608301356060820152608083013560808201526107ba60a08401610489565b60a082015260c0830135828111156107d157600080fd5b6107dd898286016104b2565b60c08301525060e0830135828111156107f557600080fd5b61080189828601610581565b60e083015250945060208601359350604086013591508082111561082457600080fd5b5061083186828701610581565b9150509250925092565b60008060006060848603121561085057600080fd5b505081359360208301359350604090920135919050565b60008060006060848603121561087c57600080fd5b8351925060208401519150604084015190509250925092565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8311156108c757600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b821515815260006020604081840152835180604085015260005b8181101561096357858101830151858201606001528201610947565b81811115610975576000606083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01692909201606001949350505050565b606081528435606082015260208501356080820152604085013560a0820152606085013560c0820152608085013560e082015260006109eb60a08701610489565b61010073ffffffffffffffffffffffffffffffffffffffff821681850152610a1660c0890189610b7e565b925081610120860152610a2e61016086018483610895565b92505050610a3f60e0880188610be5565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa085840301610140860152610a758382846108e4565b925050508560208401528281036040840152610a928185876108e4565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610ad257600080fd5b83018035915067ffffffffffffffff821115610aed57600080fd5b6020019150600581901b360382131561057a57600080fd5b604051610100810167ffffffffffffffff81118282101715610b2957610b29610cd6565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715610b7657610b76610cd6565b604052919050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610bb357600080fd5b830160208101925035905067ffffffffffffffff811115610bd357600080fd5b8060051b360383131561057a57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112610c1a57600080fd5b830160208101925035905067ffffffffffffffff811115610c3a57600080fd5b80360383131561057a57600080fd5b60008219821115610c5c57610c5c610c78565b500190565b600082821015610c7357610c73610c78565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fdfea164736f6c6343000806000a", + ABI: "[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"_isStreamsLookup\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"feedParamKey\",\"type\":\"string\"},{\"internalType\":\"string[]\",\"name\":\"feeds\",\"type\":\"string[]\"},{\"internalType\":\"string\",\"name\":\"timeParamKey\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"time\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"StreamsLookup\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"initialBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"lastBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"previousBlock\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"counter\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timeToPerform\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"isRecovered\",\"type\":\"bool\"}],\"name\":\"PerformingUpkeep\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"checkBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"performBurnAmount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"eventSig\",\"type\":\"bytes32\"},{\"internalType\":\"string[]\",\"name\":\"feeds\",\"type\":\"string[]\"}],\"internalType\":\"structCheckData\",\"name\":\"\",\"type\":\"tuple\"}],\"name\":\"_checkDataConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes[]\",\"name\":\"values\",\"type\":\"bytes[]\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkCallback\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errCode\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"extraData\",\"type\":\"bytes\"}],\"name\":\"checkErrorHandler\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"upkeepNeeded\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"txHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"blockNumber\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"blockHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"source\",\"type\":\"address\"},{\"internalType\":\"bytes32[]\",\"name\":\"topics\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"internalType\":\"structLog\",\"name\":\"log\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"checkData\",\"type\":\"bytes\"}],\"name\":\"checkLog\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"counter\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"dummyMap\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feedParamKey\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isStreamsLookup\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"performData\",\"type\":\"bytes\"}],\"name\":\"performUpkeep\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"previousPerformBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"feedParam\",\"type\":\"string\"}],\"name\":\"setFeedParamKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"value\",\"type\":\"bool\"}],\"name\":\"setShouldRetryOnErrorBool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"timeParam\",\"type\":\"string\"}],\"name\":\"setTimeParamKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shouldRetryOnError\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeParamKey\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"timeToPerform\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]", + Bin: "0x60c060405260076080819052666665656449447360c81b60a090815262000028919081620000bd565b5060408051808201909152600980825268074696d657374616d760bc1b60209092019182526200005b91600891620000bd565b503480156200006957600080fd5b5060405162001af938038062001af98339810160408190526200008c9162000163565b60006002819055436001556003819055600455600680549115156101000261ff0019909216919091179055620001cb565b828054620000cb906200018e565b90600052602060002090601f016020900481019282620000ef57600085556200013a565b82601f106200010a57805160ff19168380011785556200013a565b828001600101855582156200013a579182015b828111156200013a5782518255916020019190600101906200011d565b50620001489291506200014c565b5090565b5b808211156200014857600081556001016200014d565b6000602082840312156200017657600080fd5b815180151581146200018757600080fd5b9392505050565b600181811c90821680620001a357607f821691505b60208210811415620001c557634e487b7160e01b600052602260045260246000fd5b50919050565b61191e80620001db6000396000f3fe608060405234801561001057600080fd5b50600436106101365760003560e01c8063601d5a71116100b2578063917d895f11610081578063afb28d1f11610066578063afb28d1f146102a7578063c6066f0d146102bc578063c98f10b0146102c557600080fd5b8063917d895f1461028b5780639525d5741461029457600080fd5b8063601d5a711461024357806361bc221a146102565780637145f11b1461025f578063806b984f1461028257600080fd5b806340691db41161010957806342eb3d92116100ee57806342eb3d921461020a5780634585e33b1461021d5780634b56a42e1461023057600080fd5b806340691db4146101e657806342b0fe9e146101f957600080fd5b80630fb172fb1461013b57806313fab5901461016557806323148cee146101ad5780632cb15864146101cf575b600080fd5b61014e610149366004611104565b6102cd565b60405161015c92919061138e565b60405180910390f35b6101ab610173366004610cbd565b6006805491151562010000027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffff909216919091179055565b005b6006546101bf90610100900460ff1681565b604051901515815260200161015c565b6101d860035481565b60405190815260200161015c565b61014e6101f4366004610f8e565b6103d4565b6101ab610207366004610d77565b50565b6006546101bf9062010000900460ff1681565b6101ab61022b366004610cf8565b610659565b61014e61023e366004610be3565b6108c5565b6101ab610251366004610d3a565b610919565b6101d860045481565b6101bf61026d366004610cdf565b60006020819052908152604090205460ff1681565b6101d860015481565b6101d860025481565b6101ab6102a2366004610d3a565b610930565b6102af610943565b60405161015c91906113a9565b6101d860055481565b6102af6109d1565b6040805160028082526060828101909352600092918391816020015b60608152602001906001900390816102e95750506040805160208101889052919250016040516020818303038152906040528160008151811061032e5761032e611891565b60200260200101819052508360405160200161034a91906113a9565b6040516020818303038152906040528160018151811061036c5761036c611891565b60200260200101819052506000818560405160200161038c9291906112fa565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291905260065462010000900460ff169450925050505b9250929050565b60006060816103e584860186610d77565b905060005a905060006103f96001436117c7565b8351904091506000901561046c575b83515a61041590856117c7565b101561046c57808015610436575060008281526020819052604090205460ff165b60408051602081018590523091810191909152909150606001604051602081830303815290604052805190602001209150610408565b60408051600280825260608201909252600091816020015b606081526020019060019003908161048457905050604080516000602082015291925001604051602081830303815290604052816000815181106104ca576104ca611891565b602002602001018190525060006040516020016104f0919060ff91909116815260200190565b6040516020818303038152906040528160018151811061051257610512611891565b602002602001018190525060008a438b8b604051602001610536949392919061147b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291815287015190915061057760c08d018d611576565b600281811061058857610588611891565b90506020020135141561062257600654610100900460ff16156105ef5760608601516040517ff055e4a20000000000000000000000000000000000000000000000000000000081526105e691600791600890429086906004016113bc565b60405180910390fd5b600182826040516020016106049291906112fa565b60405160208183030381529060405297509750505050505050610651565b600082826040516020016106379291906112fa565b604051602081830303815290604052975097505050505050505b935093915050565b60035461066557436003555b436001908155600454610677916117af565b600455600154600255600061068e82840184610be3565b9150506000806000838060200190518101906106aa9190611000565b9250925092508260200151426106c091906117c7565b600555600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690556060830151821461072257600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b6000818060200190518101906107389190610e79565b905060005a9050600061074c6001436117c7565b409050600083604001518760c0015160028151811061076d5761076d611891565b6020026020010151146107dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f496e76616c6964206576656e74207369676e617475726500000000000000000060448201526064016105e6565b60208401511561084e575b83602001515a6107f790856117c7565b101561084e57808015610818575060008281526020819052604090205460ff165b604080516020810185905230918101919091529091506060016040516020818303038152906040528051906020012091506107e7565b600354600154600254600454600554600654604080519687526020870195909552938501929092526060840152608083015260ff16151560a082015232907f29eff4cb37911c3ea85db4630638cc5474fdd0631ec42215aef1d7ec96c8e63d9060c00160405180910390a250505050505050505050565b60006060600084846040516020016108de9291906112fa565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00181529190526001969095509350505050565b805161092c9060089060208401906109de565b5050565b805161092c9060079060208401906109de565b600780546109509061180e565b80601f016020809104026020016040519081016040528092919081815260200182805461097c9061180e565b80156109c95780601f1061099e576101008083540402835291602001916109c9565b820191906000526020600020905b8154815290600101906020018083116109ac57829003601f168201915b505050505081565b600880546109509061180e565b8280546109ea9061180e565b90600052602060002090601f016020900481019282610a0c5760008555610a52565b82601f10610a2557805160ff1916838001178555610a52565b82800160010185558215610a52579182015b82811115610a52578251825591602001919060010190610a37565b50610a5e929150610a62565b5090565b5b80821115610a5e5760008155600101610a63565b6000610a8a610a858461169e565b61162b565b9050828152838383011115610a9e57600080fd5b610aac8360208301846117de565b9392505050565b8051610abe816118ef565b919050565b600082601f830112610ad457600080fd5b81516020610ae4610a858361167a565b80838252828201915082860187848660051b8901011115610b0457600080fd5b60005b85811015610b2357815184529284019290840190600101610b07565b5090979650505050505050565b60008083601f840112610b4257600080fd5b50813567ffffffffffffffff811115610b5a57600080fd5b6020830191508360208285010111156103cd57600080fd5b600082601f830112610b8357600080fd5b8135610b91610a858261169e565b818152846020838601011115610ba657600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f830112610bd457600080fd5b610aac83835160208501610a77565b60008060408385031215610bf657600080fd5b823567ffffffffffffffff80821115610c0e57600080fd5b818501915085601f830112610c2257600080fd5b81356020610c32610a858361167a565b8083825282820191508286018a848660051b8901011115610c5257600080fd5b60005b85811015610c8d57813587811115610c6c57600080fd5b610c7a8d87838c0101610b72565b8552509284019290840190600101610c55565b50909750505086013592505080821115610ca657600080fd5b50610cb385828601610b72565b9150509250929050565b600060208284031215610ccf57600080fd5b81358015158114610aac57600080fd5b600060208284031215610cf157600080fd5b5035919050565b60008060208385031215610d0b57600080fd5b823567ffffffffffffffff811115610d2257600080fd5b610d2e85828601610b30565b90969095509350505050565b600060208284031215610d4c57600080fd5b813567ffffffffffffffff811115610d6357600080fd5b610d6f84828501610b72565b949350505050565b60006020808385031215610d8a57600080fd5b823567ffffffffffffffff80821115610da257600080fd5b9084019060808287031215610db657600080fd5b610dbe6115de565b82358152838301358482015260408301356040820152606083013582811115610de657600080fd5b80840193505086601f840112610dfb57600080fd5b8235610e09610a858261167a565b8082825286820191508686018a888560051b8901011115610e2957600080fd5b6000805b85811015610e6457823588811115610e43578283fd5b610e518e8c838d0101610b72565b8652509389019391890191600101610e2d565b50505060608401525090979650505050505050565b60006020808385031215610e8c57600080fd5b825167ffffffffffffffff80821115610ea457600080fd5b9084019060808287031215610eb857600080fd5b610ec06115de565b82518152838301518482015260408084015181830152606084015183811115610ee857600080fd5b80850194505087601f850112610efd57600080fd5b8351610f0b610a858261167a565b8082825287820191508787018b898560051b8a01011115610f2b57600080fd5b60005b84811015610f7957815188811115610f4557600080fd5b8901603f81018e13610f5657600080fd5b610f668e8c830151898401610a77565b8552509289019290890190600101610f2e565b50506060850152509198975050505050505050565b600080600060408486031215610fa357600080fd5b833567ffffffffffffffff80821115610fbb57600080fd5b908501906101008288031215610fd057600080fd5b90935060208501359080821115610fe657600080fd5b50610ff386828701610b30565b9497909650939450505050565b60008060006060848603121561101557600080fd5b835167ffffffffffffffff8082111561102d57600080fd5b90850190610100828803121561104257600080fd5b61104a611607565b825181526020830151602082015260408301516040820152606083015160608201526080830151608082015261108260a08401610ab3565b60a082015260c08301518281111561109957600080fd5b6110a589828601610ac3565b60c08301525060e0830151828111156110bd57600080fd5b6110c989828601610bc3565b60e0830152506020870151604088015191965094509150808211156110ed57600080fd5b506110fa86828701610bc3565b9150509250925092565b6000806040838503121561111757600080fd5b82359150602083013567ffffffffffffffff81111561113557600080fd5b610cb385828601610b72565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83111561117357600080fd5b8260051b8083602087013760009401602001938452509192915050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600081518084526111f18160208601602086016117de565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b8054600090600181811c908083168061123d57607f831692505b6020808410821415611278577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b8388526020880182801561129357600181146112c2576112ed565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff008716825282820197506112ed565b60008981526020902060005b878110156112e7578154848201529086019084016112ce565b83019850505b5050505050505092915050565b6000604082016040835280855180835260608501915060608160051b8601019250602080880160005b8381101561136f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa088870301855261135d8683516111d9565b95509382019390820190600101611323565b50508584038187015250505061138581856111d9565b95945050505050565b8215158152604060208201526000610d6f60408301846111d9565b602081526000610aac60208301846111d9565b60a0815260006113cf60a0830188611223565b6020838203818501528188518084528284019150828160051b850101838b0160005b8381101561143d577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe087840301855261142b8383516111d9565b948601949250908501906001016113f1565b50508681036040880152611451818b611223565b945050505050846060840152828103608084015261146f81856111d9565b98975050505050505050565b606081528435606082015260208501356080820152604085013560a0820152606085013560c0820152608085013560e0820152600060a08601356114be816118ef565b6101006114e28185018373ffffffffffffffffffffffffffffffffffffffff169052565b6114ef60c08901896116e4565b92508161012086015261150761016086018483611141565b9250505061151860e088018861174b565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08584030161014086015261154e838284611190565b92505050856020840152828103604084015261156b818587611190565b979650505050505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126115ab57600080fd5b83018035915067ffffffffffffffff8211156115c657600080fd5b6020019150600581901b36038213156103cd57600080fd5b6040516080810167ffffffffffffffff81118282101715611601576116016118c0565b60405290565b604051610100810167ffffffffffffffff81118282101715611601576116016118c0565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715611672576116726118c0565b604052919050565b600067ffffffffffffffff821115611694576116946118c0565b5060051b60200190565b600067ffffffffffffffff8211156116b8576116b86118c0565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261171957600080fd5b830160208101925035905067ffffffffffffffff81111561173957600080fd5b8060051b36038313156103cd57600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261178057600080fd5b830160208101925035905067ffffffffffffffff8111156117a057600080fd5b8036038313156103cd57600080fd5b600082198211156117c2576117c2611862565b500190565b6000828210156117d9576117d9611862565b500390565b60005b838110156117f95781810151838201526020016117e1565b83811115611808576000848401525b50505050565b600181811c9082168061182257607f821691505b6020821081141561185c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff8116811461020757600080fdfea164736f6c6343000806000a", } var SimpleLogUpkeepCounterABI = SimpleLogUpkeepCounterMetaData.ABI var SimpleLogUpkeepCounterBin = SimpleLogUpkeepCounterMetaData.Bin -func DeploySimpleLogUpkeepCounter(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SimpleLogUpkeepCounter, error) { +func DeploySimpleLogUpkeepCounter(auth *bind.TransactOpts, backend bind.ContractBackend, _isStreamsLookup bool) (common.Address, *types.Transaction, *SimpleLogUpkeepCounter, error) { parsed, err := SimpleLogUpkeepCounterMetaData.GetAbi() if err != nil { return common.Address{}, nil, nil, err @@ -65,7 +66,7 @@ func DeploySimpleLogUpkeepCounter(auth *bind.TransactOpts, backend bind.Contract return common.Address{}, nil, nil, errors.New("GetABI returned nil") } - address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SimpleLogUpkeepCounterBin), backend) + address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SimpleLogUpkeepCounterBin), backend, _isStreamsLookup) if err != nil { return common.Address{}, nil, nil, err } @@ -188,6 +189,59 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorRaw) Transact(opt return _SimpleLogUpkeepCounter.Contract.contract.Transact(opts, method, params...) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckCallback(opts *bind.CallOpts, values [][]byte, extraData []byte) (bool, []byte, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkCallback", values, extraData) + + if err != nil { + return *new(bool), *new([]byte), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + out1 := *abi.ConvertType(out[1], new([]byte)).(*[]byte) + + return out0, out1, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckCallback(values [][]byte, extraData []byte) (bool, []byte, error) { + return _SimpleLogUpkeepCounter.Contract.CheckCallback(&_SimpleLogUpkeepCounter.CallOpts, values, extraData) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) CheckCallback(values [][]byte, extraData []byte) (bool, []byte, error) { + return _SimpleLogUpkeepCounter.Contract.CheckCallback(&_SimpleLogUpkeepCounter.CallOpts, values, extraData) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckErrorHandler(opts *bind.CallOpts, errCode *big.Int, extraData []byte) (CheckErrorHandler, + + error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkErrorHandler", errCode, extraData) + + outstruct := new(CheckErrorHandler) + if err != nil { + return *outstruct, err + } + + outstruct.UpkeepNeeded = *abi.ConvertType(out[0], new(bool)).(*bool) + outstruct.PerformData = *abi.ConvertType(out[1], new([]byte)).(*[]byte) + + return *outstruct, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) CheckErrorHandler(errCode *big.Int, extraData []byte) (CheckErrorHandler, + + error) { + return _SimpleLogUpkeepCounter.Contract.CheckErrorHandler(&_SimpleLogUpkeepCounter.CallOpts, errCode, extraData) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) CheckErrorHandler(errCode *big.Int, extraData []byte) (CheckErrorHandler, + + error) { + return _SimpleLogUpkeepCounter.Contract.CheckErrorHandler(&_SimpleLogUpkeepCounter.CallOpts, errCode, extraData) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) CheckLog(opts *bind.CallOpts, log Log, checkData []byte) (bool, []byte, error) { var out []interface{} err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "checkLog", log, checkData) @@ -255,6 +309,28 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) DummyMap(arg return _SimpleLogUpkeepCounter.Contract.DummyMap(&_SimpleLogUpkeepCounter.CallOpts, arg0) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) FeedParamKey(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "feedParamKey") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) FeedParamKey() (string, error) { + return _SimpleLogUpkeepCounter.Contract.FeedParamKey(&_SimpleLogUpkeepCounter.CallOpts) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) FeedParamKey() (string, error) { + return _SimpleLogUpkeepCounter.Contract.FeedParamKey(&_SimpleLogUpkeepCounter.CallOpts) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) InitialBlock(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "initialBlock") @@ -277,9 +353,9 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) InitialBlock return _SimpleLogUpkeepCounter.Contract.InitialBlock(&_SimpleLogUpkeepCounter.CallOpts) } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) IsRecovered(opts *bind.CallOpts) (bool, error) { +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) IsStreamsLookup(opts *bind.CallOpts) (bool, error) { var out []interface{} - err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "isRecovered") + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "isStreamsLookup") if err != nil { return *new(bool), err @@ -291,12 +367,12 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) IsRecovered(opts *b } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) IsRecovered() (bool, error) { - return _SimpleLogUpkeepCounter.Contract.IsRecovered(&_SimpleLogUpkeepCounter.CallOpts) +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) IsStreamsLookup() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.IsStreamsLookup(&_SimpleLogUpkeepCounter.CallOpts) } -func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) IsRecovered() (bool, error) { - return _SimpleLogUpkeepCounter.Contract.IsRecovered(&_SimpleLogUpkeepCounter.CallOpts) +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) IsStreamsLookup() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.IsStreamsLookup(&_SimpleLogUpkeepCounter.CallOpts) } func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) LastBlock(opts *bind.CallOpts) (*big.Int, error) { @@ -343,6 +419,50 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) PreviousPerf return _SimpleLogUpkeepCounter.Contract.PreviousPerformBlock(&_SimpleLogUpkeepCounter.CallOpts) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) ShouldRetryOnError(opts *bind.CallOpts) (bool, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "shouldRetryOnError") + + if err != nil { + return *new(bool), err + } + + out0 := *abi.ConvertType(out[0], new(bool)).(*bool) + + return out0, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) ShouldRetryOnError() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.ShouldRetryOnError(&_SimpleLogUpkeepCounter.CallOpts) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) ShouldRetryOnError() (bool, error) { + return _SimpleLogUpkeepCounter.Contract.ShouldRetryOnError(&_SimpleLogUpkeepCounter.CallOpts) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) TimeParamKey(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "timeParamKey") + + if err != nil { + return *new(string), err + } + + out0 := *abi.ConvertType(out[0], new(string)).(*string) + + return out0, err + +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) TimeParamKey() (string, error) { + return _SimpleLogUpkeepCounter.Contract.TimeParamKey(&_SimpleLogUpkeepCounter.CallOpts) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCallerSession) TimeParamKey() (string, error) { + return _SimpleLogUpkeepCounter.Contract.TimeParamKey(&_SimpleLogUpkeepCounter.CallOpts) +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterCaller) TimeToPerform(opts *bind.CallOpts) (*big.Int, error) { var out []interface{} err := _SimpleLogUpkeepCounter.contract.Call(opts, &out, "timeToPerform") @@ -389,6 +509,42 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) PerformU return _SimpleLogUpkeepCounter.Contract.PerformUpkeep(&_SimpleLogUpkeepCounter.TransactOpts, performData) } +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) SetFeedParamKey(opts *bind.TransactOpts, feedParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.contract.Transact(opts, "setFeedParamKey", feedParam) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) SetFeedParamKey(feedParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetFeedParamKey(&_SimpleLogUpkeepCounter.TransactOpts, feedParam) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) SetFeedParamKey(feedParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetFeedParamKey(&_SimpleLogUpkeepCounter.TransactOpts, feedParam) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) SetShouldRetryOnErrorBool(opts *bind.TransactOpts, value bool) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.contract.Transact(opts, "setShouldRetryOnErrorBool", value) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) SetShouldRetryOnErrorBool(value bool) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetShouldRetryOnErrorBool(&_SimpleLogUpkeepCounter.TransactOpts, value) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) SetShouldRetryOnErrorBool(value bool) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetShouldRetryOnErrorBool(&_SimpleLogUpkeepCounter.TransactOpts, value) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactor) SetTimeParamKey(opts *bind.TransactOpts, timeParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.contract.Transact(opts, "setTimeParamKey", timeParam) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterSession) SetTimeParamKey(timeParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetTimeParamKey(&_SimpleLogUpkeepCounter.TransactOpts, timeParam) +} + +func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterTransactorSession) SetTimeParamKey(timeParam string) (*types.Transaction, error) { + return _SimpleLogUpkeepCounter.Contract.SetTimeParamKey(&_SimpleLogUpkeepCounter.TransactOpts, timeParam) +} + type SimpleLogUpkeepCounterPerformingUpkeepIterator struct { Event *SimpleLogUpkeepCounterPerformingUpkeep @@ -522,6 +678,11 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounterFilterer) ParsePerformingUp return event, nil } +type CheckErrorHandler struct { + UpkeepNeeded bool + PerformData []byte +} + func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) ParseLog(log types.Log) (generated.AbigenLog, error) { switch log.Topics[0] { case _SimpleLogUpkeepCounter.abi.Events["PerformingUpkeep"].ID: @@ -541,26 +702,44 @@ func (_SimpleLogUpkeepCounter *SimpleLogUpkeepCounter) Address() common.Address } type SimpleLogUpkeepCounterInterface interface { + CheckCallback(opts *bind.CallOpts, values [][]byte, extraData []byte) (bool, []byte, error) + + CheckErrorHandler(opts *bind.CallOpts, errCode *big.Int, extraData []byte) (CheckErrorHandler, + + error) + CheckLog(opts *bind.CallOpts, log Log, checkData []byte) (bool, []byte, error) Counter(opts *bind.CallOpts) (*big.Int, error) DummyMap(opts *bind.CallOpts, arg0 [32]byte) (bool, error) + FeedParamKey(opts *bind.CallOpts) (string, error) + InitialBlock(opts *bind.CallOpts) (*big.Int, error) - IsRecovered(opts *bind.CallOpts) (bool, error) + IsStreamsLookup(opts *bind.CallOpts) (bool, error) LastBlock(opts *bind.CallOpts) (*big.Int, error) PreviousPerformBlock(opts *bind.CallOpts) (*big.Int, error) + ShouldRetryOnError(opts *bind.CallOpts) (bool, error) + + TimeParamKey(opts *bind.CallOpts) (string, error) + TimeToPerform(opts *bind.CallOpts) (*big.Int, error) CheckDataConfig(opts *bind.TransactOpts, arg0 CheckData) (*types.Transaction, error) PerformUpkeep(opts *bind.TransactOpts, performData []byte) (*types.Transaction, error) + SetFeedParamKey(opts *bind.TransactOpts, feedParam string) (*types.Transaction, error) + + SetShouldRetryOnErrorBool(opts *bind.TransactOpts, value bool) (*types.Transaction, error) + + SetTimeParamKey(opts *bind.TransactOpts, timeParam string) (*types.Transaction, error) + FilterPerformingUpkeep(opts *bind.FilterOpts, from []common.Address) (*SimpleLogUpkeepCounterPerformingUpkeepIterator, error) WatchPerformingUpkeep(opts *bind.WatchOpts, sink chan<- *SimpleLogUpkeepCounterPerformingUpkeep, from []common.Address) (event.Subscription, error) diff --git a/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go b/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go index 8320483bc4e..68553db104e 100644 --- a/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go +++ b/core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go @@ -31,8 +31,8 @@ var ( ) var VRFV2PlusWrapperMetaData = &bind.MetaData{ - ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_linkNativeFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_coordinator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"expectedMinimumLength\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"actualLength\",\"type\":\"uint16\"}],\"name\":\"IncorrectExtraArgsLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"max\",\"type\":\"uint8\"}],\"name\":\"InvalidPremiumPercentage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LINKPaymentInRequestRandomWordsInNative\",\"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\":\"NativePaymentInOnTokenTransfer\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIdMissing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"wrapperGasOverhead\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"coordinatorGasOverhead\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"wrapperNativePremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"wrapperLinkPremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"maxNumWords\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"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\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Disabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Enabled\",\"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\":\"uint32\",\"name\":\"size\",\"type\":\"uint32\"}],\"name\":\"FulfillmentTxSizeSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"LinkNativeFeedSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeWithdrawn\",\"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\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"WrapperFulfillmentFailed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUBSCRIPTION_ID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"calculateRequestPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"calculateRequestPriceNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isLinkMode\",\"type\":\"bool\"}],\"name\":\"checkPaymentMode\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"enable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"_requestGasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateRequestPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"_requestGasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateRequestPriceNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"wrapperGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"coordinatorGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"wrapperNativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"wrapperLinkPremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"maxNumWords\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"link\",\"outputs\":[{\"internalType\":\"address\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"requestRandomWordsInNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_callbacks\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"requestGasPrice\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_configured\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_disabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fulfillmentTxSizeBytes\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_linkNativeFeed\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contractIVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_wrapperGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_coordinatorGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"_wrapperNativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"_wrapperLinkPremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_maxNumWords\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"_stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"_fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"_fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"size\",\"type\":\"uint32\"}],\"name\":\"setFulfillmentTxSize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"linkNativeFeed\",\"type\":\"address\"}],\"name\":\"setLinkNativeFeed\",\"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\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60c06040526007805463ffffffff60201b1916650244000000001790553480156200002957600080fd5b5060405162003ca138038062003ca18339810160408190526200004c91620002ed565b813380600081620000a45760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000d757620000d78162000225565b5050506001600160a01b038116620001025760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392831617905584166200013e5760405163d92e233d60e01b815260040160405180910390fd5b6001600160a01b0380851660a0528316156200017a5760068054600160201b600160c01b0319166401000000006001600160a01b038616021790555b806000036200019c5760405163a81c0bef60e01b815260040160405180910390fd5b60025460405163dc311dd360e01b8152600481018390526001600160a01b039091169063dc311dd390602401600060405180830381865afa158015620001e6573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200021091908101906200036d565b50505060809290925250620004969350505050565b336001600160a01b038216036200027f5760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009b565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b0381168114620002e857600080fd5b919050565b600080600080608085870312156200030457600080fd5b6200030f85620002d0565b93506200031f60208601620002d0565b92506200032f60408601620002d0565b6060959095015193969295505050565b80516001600160601b0381168114620002e857600080fd5b634e487b7160e01b600052604160045260246000fd5b600080600080600060a086880312156200038657600080fd5b62000391866200033f565b94506020620003a28188016200033f565b60408801519095506001600160401b038082168214620003c157600080fd5b819550620003d260608a01620002d0565b94506080890151915080821115620003e957600080fd5b818901915089601f830112620003fe57600080fd5b81518181111562000413576200041362000357565b8060051b604051601f19603f830116810181811085821117156200043b576200043b62000357565b60405291825284820192508381018501918c8311156200045a57600080fd5b938501935b8285101562000483576200047385620002d0565b845293850193928501926200045f565b8096505050505050509295509295909350565b60805160a0516137c2620004df6000396000818161029601528181610f2901528181610ff80152611b520152600081816101e4015281816117a80152611d3801526137c26000f3fe6080604052600436106101cd5760003560e01c80637fb5d19d116100f7578063a608a1e111610095578063f254bdc711610064578063f254bdc71461074f578063f2fde38b14610784578063fc2a88c3146107a4578063fc2dbebc146107ba57600080fd5b8063a608a1e1146105d2578063bf17e55914610605578063c3f909d414610625578063cdd8d8851461071557600080fd5b80639cfc058e116100d15780639cfc058e1461055d5780639eccacf614610570578063a3907d711461059d578063a4c0ed36146105b257600080fd5b80637fb5d19d146104f25780638da5cb5b146105125780638ea981171461053d57600080fd5b80633255c4561161016f57806351cff8d91161013e57806351cff8d91461045b57806357a8070a1461047b57806365059654146104bd57806379ba5097146104dd57600080fd5b80633255c456146103305780634306d3541461035057806348baa1c5146103705780634b1609351461043b57600080fd5b80631c4695f4116101ab5780631c4695f4146102875780631fe543e3146102db5780632f2770db146102fb5780632f622e6b1461031057600080fd5b8063030932bb146101d2578063181f5a771461021957806318b6f4c814610265575b600080fd5b3480156101de57600080fd5b506102067f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561022557600080fd5b50604080518082018252601281527f56524656325772617070657220312e302e300000000000000000000000000000602082015290516102109190612e59565b34801561027157600080fd5b50610285610280366004612f86565b6107da565b005b34801561029357600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610210565b3480156102e757600080fd5b506102856102f6366004612fd8565b610962565b34801561030757600080fd5b506102856109df565b34801561031c57600080fd5b5061028561032b3660046130ae565b610a52565b34801561033c57600080fd5b5061020661034b3660046130dd565b610b79565b34801561035c57600080fd5b5061020661036b366004613107565b610c9f565b34801561037c57600080fd5b506103fa61038b366004613122565b60086020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000810463ffffffff16907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1683565b6040805173ffffffffffffffffffffffffffffffffffffffff909416845263ffffffff909216602084015267ffffffffffffffff1690820152606001610210565b34801561044757600080fd5b50610206610456366004613107565b610dd3565b34801561046757600080fd5b506102856104763660046130ae565b610ef0565b34801561048757600080fd5b506002546104ad9074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610210565b3480156104c957600080fd5b506102856104d83660046130ae565b6110f1565b3480156104e957600080fd5b5061028561117d565b3480156104fe57600080fd5b5061020661050d3660046130dd565b61127a565b34801561051e57600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102b6565b34801561054957600080fd5b506102856105583660046130ae565b6113ad565b61020661056b366004613196565b611531565b34801561057c57600080fd5b506002546102b69073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105a957600080fd5b506102856119d5565b3480156105be57600080fd5b506102856105cd36600461320c565b611a30565b3480156105de57600080fd5b506002546104ad907501000000000000000000000000000000000000000000900460ff1681565b34801561061157600080fd5b50610285610620366004613107565b611f96565b34801561063157600080fd5b506005546006546007546003546002546040805195865263ffffffff94851660208701526c010000000000000000000000008404851690860152700100000000000000000000000000000000830484166060860152838316608086015268010000000000000000830490931660a085015260ff740100000000000000000000000000000000000000008304811660c08601527501000000000000000000000000000000000000000000909204821660e08501526101008401527601000000000000000000000000000000000000000000009091041661012082015261014001610210565b34801561072157600080fd5b5060075461073a90640100000000900463ffffffff1681565b60405163ffffffff9091168152602001610210565b34801561075b57600080fd5b506006546102b690640100000000900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561079057600080fd5b5061028561079f3660046130ae565b61200b565b3480156107b057600080fd5b5061020660045481565b3480156107c657600080fd5b506102856107d5366004613277565b61201f565b815160000361081e578061081a576040517f6b81746e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b8151602411156108785781516040517f51200dce00000000000000000000000000000000000000000000000000000000815261086f9160249160040161ffff92831681529116602082015260400190565b60405180910390fd5b60008260238151811061088d5761088d613323565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f01000000000000000000000000000000000000000000000000000000000000001490508080156108e35750815b1561091a576040517f6048aa6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015610926575081155b1561095d576040517f6b81746e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60025473ffffffffffffffffffffffffffffffffffffffff1633146109d5576002546040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff909116602482015260440161086f565b61081a82826122f0565b6109e76124d3565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790556040517f75884cdadc4a89e8b545db800057f06ec7f5338a08183c7ba515f2bfdd9fe1e190600090a1565b610a5a6124d3565b604051479060009073ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d8060008114610ab4576040519150601f19603f3d011682016040523d82523d6000602084013e610ab9565b606091505b5050905080610b24576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6661696c656420746f207769746864726177206e617469766500000000000000604482015260640161086f565b8273ffffffffffffffffffffffffffffffffffffffff167fc303ca808382409472acbbf899c316cf439f409f6584aae22df86dfa3c9ed50483604051610b6c91815260200190565b60405180910390a2505050565b60025460009074010000000000000000000000000000000000000000900460ff16610c00576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff1615610c86576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b610c968363ffffffff1683612556565b90505b92915050565b60025460009074010000000000000000000000000000000000000000900460ff16610d26576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff1615610dac576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b6000610db6612651565b509050610dca8363ffffffff163a836127a4565b9150505b919050565b60025460009074010000000000000000000000000000000000000000900460ff16610e5a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff1615610ee0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b610c998263ffffffff163a612556565b610ef86124d3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610f85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa99190613352565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015611043573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611067919061336b565b61109d576040517f7c07fc4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516110e591815260200190565b60405180910390a25050565b6110f96124d3565b600680547fffffffffffffffff0000000000000000000000000000000000000000ffffffff1664010000000073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527fc252955f9bd8c6ea6e3cc712bbad31005d85cec90e73b147b4d6e8326242efdf906020015b60405180910390a150565b60015473ffffffffffffffffffffffffffffffffffffffff1633146111fe576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e657200000000000000000000604482015260640161086f565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60025460009074010000000000000000000000000000000000000000900460ff16611301576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff1615611387576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b6000611391612651565b5090506113a58463ffffffff1684836127a4565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633148015906113ed575060025473ffffffffffffffffffffffffffffffffffffffff163314155b15611471573361141260005473ffffffffffffffffffffffffffffffffffffffff1690565b6002546040517f061db9c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9384166004820152918316602483015291909116604482015260640161086f565b73ffffffffffffffffffffffffffffffffffffffff81166114be576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be690602001611172565b60025460009074010000000000000000000000000000000000000000900460ff166115b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff161561163e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b61167d83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506107da915050565b6000611688876128e4565b9050600061169c8863ffffffff163a612556565b905080341015611708576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f77000000000000000000000000000000000000000000604482015260640161086f565b600254760100000000000000000000000000000000000000000000900460ff1663ffffffff87161115611797576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f2068696768000000000000000000000000000000604482015260640161086f565b6040805160c08101825260035481527f0000000000000000000000000000000000000000000000000000000000000000602082015261ffff89169181019190915260075460009190606082019063ffffffff166117f4868d6133be565b6117fe91906133be565b63ffffffff1681526020018863ffffffff16815260200187878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509152506002546040517f9b1c385e00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff1690639b1c385e906118a49084906004016133e2565b6020604051808303816000875af11580156118c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118e79190613352565b6040805160608101825233815263ffffffff808d16602080840191825267ffffffffffffffff3a81168587019081526000888152600890935295909120935184549251955190911678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff9590931674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff91909116171792909216919091179055935050505095945050505050565b6119dd6124d3565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1690556040517fc0f961051f97b04c496472d11cb6170d844e4b2c9dfd3b602a4fa0139712d48490600090a1565b60025474010000000000000000000000000000000000000000900460ff16611ab4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e6669677572656400000000000000604482015260640161086f565b6002547501000000000000000000000000000000000000000000900460ff1615611b3a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c656400000000000000000000000000604482015260640161086f565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611bd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c792063616c6c61626c652066726f6d204c494e4b000000000000000000604482015260640161086f565b6000808080611bea8587018761343f565b9350935093509350611bfd8160016107da565b6000611c08856128e4565b9050600080611c15612651565b915091506000611c2c8863ffffffff163a856127a4565b9050808b1015611c98576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f77000000000000000000000000000000000000000000604482015260640161086f565b600254760100000000000000000000000000000000000000000000900460ff1663ffffffff87161115611d27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f2068696768000000000000000000000000000000604482015260640161086f565b6040805160c08101825260035481527f0000000000000000000000000000000000000000000000000000000000000000602082015261ffff89169181019190915260075460009190606082019063ffffffff16611d84888d6133be565b611d8e91906133be565b63ffffffff908116825289166020820152604090810188905260025490517f9b1c385e00000000000000000000000000000000000000000000000000000000815291925060009173ffffffffffffffffffffffffffffffffffffffff90911690639b1c385e90611e029085906004016133e2565b6020604051808303816000875af1158015611e21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e459190613352565b905060405180606001604052808f73ffffffffffffffffffffffffffffffffffffffff1681526020018b63ffffffff1681526020013a67ffffffffffffffff168152506008600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550905050806004819055508315611f86576005546040805183815260208101929092527f6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a910160405180910390a15b5050505050505050505050505050565b611f9e6124d3565b600780547fffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff1664010000000063ffffffff8416908102919091179091556040519081527f697b48b8b76cebb09a54ec4ff810e8a181c96f65395d51c744db09c115d1d5d090602001611172565b6120136124d3565b61201c816128fc565b50565b6120276124d3565b8163ffffffff168163ffffffff16111561207d576040517f2780dcb200000000000000000000000000000000000000000000000000000000815263ffffffff80831660048301528316602482015260440161086f565b609b60ff891611156120c7576040517f3acc511a00000000000000000000000000000000000000000000000000000000815260ff89166004820152609b602482015260440161086f565b609b60ff88161115612111576040517f3acc511a00000000000000000000000000000000000000000000000000000000815260ff88166004820152609b602482015260440161086f565b89600760006101000a81548163ffffffff021916908363ffffffff16021790555088600760086101000a81548163ffffffff021916908363ffffffff16021790555087600760146101000a81548160ff021916908360ff16021790555086600760156101000a81548160ff021916908360ff1602179055508560038190555084600260166101000a81548160ff021916908360ff1602179055506001600260146101000a81548160ff02191690831515021790555083600660006101000a81548163ffffffff021916908363ffffffff16021790555082600581905550816007600c6101000a81548163ffffffff021916908363ffffffff16021790555080600760106101000a81548163ffffffff021916908363ffffffff1602179055507fb18fd84519589131d50ae195b0aea1b042c3c0b25a53bb894d9d81c78980c20f8a8a8a8a8a8a8a8a8a600760109054906101000a900463ffffffff166040516122dc9a9998979695949392919063ffffffff9a8b168152988a1660208a015260ff97881660408a0152958716606089015260808801949094529190941660a086015292851660c085015260e08401929092529083166101008301529091166101208201526101400190565b60405180910390a150505050505050505050565b60008281526008602081815260408084208151606081018352815473ffffffffffffffffffffffffffffffffffffffff808216835274010000000000000000000000000000000000000000820463ffffffff1683870152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff1693820193909352878652939092529290558051909181166123eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f72657175657374206e6f7420666f756e64000000000000000000000000000000604482015260640161086f565b600080631fe543e360e01b86866040516024016124099291906134ae565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050509050600061247f856020015163ffffffff1685846129f1565b9050806124ca5760405173ffffffffffffffffffffffffffffffffffffffff85169088907fc551b83c151f2d1c7eeb938ac59008e0409f1c1dc1e2f112449d4d79b458902290600090a35b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314612554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e657200000000000000000000604482015260640161086f565b565b600754600090819061256e9063ffffffff16846134fc565b60075490915060009061258e90640100000000900463ffffffff16612a3d565b6007546125ad9068010000000000000000900463ffffffff1687613513565b6125b790866134fc565b6125c19190613513565b6007549091506000906125ef906c01000000000000000000000000900463ffffffff1664e8d4a510006134fc565b60075460649061261a9074010000000000000000000000000000000000000000900460ff1682613526565b6126279060ff16856134fc565b612631919061356e565b61263b9190613513565b90506126478184613513565b9695505050505050565b600654604080517ffeaf968c0000000000000000000000000000000000000000000000000000000081529051600092839263ffffffff8216928492640100000000900473ffffffffffffffffffffffffffffffffffffffff169163feaf968c9160048083019260a09291908290030181865afa1580156126d5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126f9919061359c565b50919650909250505063ffffffff821615801590612725575061271c81426135ec565b8263ffffffff16105b925082156127335760055493505b600084121561279e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c6964204c494e4b2077656920707269636500000000000000000000604482015260640161086f565b50509091565b60075460009081906127bc9063ffffffff16856134fc565b6007549091506000906127dc90640100000000900463ffffffff16612a3d565b6007546127fb9068010000000000000000900463ffffffff1688613513565b61280590876134fc565b61280f9190613513565b60075490915060009061284e9063ffffffff70010000000000000000000000000000000082048116916c010000000000000000000000009004166135ff565b6128639063ffffffff1664e8d4a510006134fc565b60075460649061288f907501000000000000000000000000000000000000000000900460ff1682613526565b61289c9060ff16856134fc565b6128a6919061356e565b6128b09190613513565b9050846128bd8285613513565b6128cf90670de0b6b3a76400006134fc565b6128d9919061356e565b979650505050505050565b60006128f1603f8361361c565b610c999060016133be565b3373ffffffffffffffffffffffffffffffffffffffff82160361297b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640161086f565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005a611388811015612a0357600080fd5b611388810390508460408204820311612a1b57600080fd5b50823b612a2757600080fd5b60008083516020850160008789f1949350505050565b600046612a4981612afe565b15612ade576000606c73ffffffffffffffffffffffffffffffffffffffff166341b247a86040518163ffffffff1660e01b815260040160c060405180830381865afa158015612a9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ac0919061363f565b5050505091505083608c612ad49190613513565b6113a590826134fc565b612ae781612b21565b15612af557610dca83612b5b565b50600092915050565b600061a4b1821480612b12575062066eed82145b80610c9957505062066eee1490565b6000600a821480612b3357506101a482145b80612b40575062aa37dc82145b80612b4c575061210582145b80610c9957505062014a331490565b60008073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663519b4bd36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612bbd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612be19190613352565b9050600080612bf081866135ec565b90506000612bff8260106134fc565b612c0a8460046134fc565b612c149190613513565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff16630c18c1626040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c9b9190613352565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663f45e65d86040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cfe573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d229190613352565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d85573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612da99190613352565b90506000612db882600a6137a9565b905060008184612dc88789613513565b612dd2908c6134fc565b612ddc91906134fc565b612de6919061356e565b9b9a5050505050505050505050565b6000815180845260005b81811015612e1b57602081850181015186830182015201612dff565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c966020830184612df5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612ee257612ee2612e6c565b604052919050565b600082601f830112612efb57600080fd5b813567ffffffffffffffff811115612f1557612f15612e6c565b612f4660207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612e9b565b818152846020838601011115612f5b57600080fd5b816020850160208301376000918101602001919091529392505050565b801515811461201c57600080fd5b60008060408385031215612f9957600080fd5b823567ffffffffffffffff811115612fb057600080fd5b612fbc85828601612eea565b9250506020830135612fcd81612f78565b809150509250929050565b60008060408385031215612feb57600080fd5b8235915060208084013567ffffffffffffffff8082111561300b57600080fd5b818601915086601f83011261301f57600080fd5b81358181111561303157613031612e6c565b8060051b9150613042848301612e9b565b818152918301840191848101908984111561305c57600080fd5b938501935b8385101561307a57843582529385019390850190613061565b8096505050505050509250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610dce57600080fd5b6000602082840312156130c057600080fd5b610c968261308a565b803563ffffffff81168114610dce57600080fd5b600080604083850312156130f057600080fd5b6130f9836130c9565b946020939093013593505050565b60006020828403121561311957600080fd5b610c96826130c9565b60006020828403121561313457600080fd5b5035919050565b803561ffff81168114610dce57600080fd5b60008083601f84011261315f57600080fd5b50813567ffffffffffffffff81111561317757600080fd5b60208301915083602082850101111561318f57600080fd5b9250929050565b6000806000806000608086880312156131ae57600080fd5b6131b7866130c9565b94506131c56020870161313b565b93506131d3604087016130c9565b9250606086013567ffffffffffffffff8111156131ef57600080fd5b6131fb8882890161314d565b969995985093965092949392505050565b6000806000806060858703121561322257600080fd5b61322b8561308a565b935060208501359250604085013567ffffffffffffffff81111561324e57600080fd5b61325a8782880161314d565b95989497509550505050565b803560ff81168114610dce57600080fd5b6000806000806000806000806000806101408b8d03121561329757600080fd5b6132a08b6130c9565b99506132ae60208c016130c9565b98506132bc60408c01613266565b97506132ca60608c01613266565b965060808b013595506132df60a08c01613266565b94506132ed60c08c016130c9565b935060e08b013592506133036101008c016130c9565b91506133126101208c016130c9565b90509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561336457600080fd5b5051919050565b60006020828403121561337d57600080fd5b815161338881612f78565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff8181168382160190808211156133db576133db61338f565b5092915050565b60208152815160208201526020820151604082015261ffff60408301511660608201526000606083015163ffffffff80821660808501528060808601511660a0850152505060a083015160c0808401526113a560e0840182612df5565b6000806000806080858703121561345557600080fd5b61345e856130c9565b935061346c6020860161313b565b925061347a604086016130c9565b9150606085013567ffffffffffffffff81111561349657600080fd5b6134a287828801612eea565b91505092959194509250565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156134ef578451835293830193918301916001016134d3565b5090979650505050505050565b8082028115828204841417610c9957610c9961338f565b80820180821115610c9957610c9961338f565b60ff8181168382160190811115610c9957610c9961338f565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261357d5761357d61353f565b500490565b805169ffffffffffffffffffff81168114610dce57600080fd5b600080600080600060a086880312156135b457600080fd5b6135bd86613582565b94506020860151935060408601519250606086015191506135e060808701613582565b90509295509295909350565b81810381811115610c9957610c9961338f565b63ffffffff8281168282160390808211156133db576133db61338f565b600063ffffffff808416806136335761363361353f565b92169190910492915050565b60008060008060008060c0878903121561365857600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b600181815b808511156136e257817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156136c8576136c861338f565b808516156136d557918102915b93841c939080029061368e565b509250929050565b6000826136f957506001610c99565b8161370657506000610c99565b816001811461371c576002811461372657613742565b6001915050610c99565b60ff8411156137375761373761338f565b50506001821b610c99565b5060208310610133831016604e8410600b8410161715613765575081810a610c99565b61376f8383613689565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048211156137a1576137a161338f565b029392505050565b6000610c9683836136ea56fea164736f6c6343000813000a", + ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_link\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_linkNativeFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_coordinator\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_subId\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"FailedToTransferLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"expectedMinimumLength\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"actualLength\",\"type\":\"uint16\"}],\"name\":\"IncorrectExtraArgsLength\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"premiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"max\",\"type\":\"uint8\"}],\"name\":\"InvalidPremiumPercentage\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"LINKPaymentInRequestRandomWordsInNative\",\"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\":\"NativePaymentInOnTokenTransfer\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"want\",\"type\":\"address\"}],\"name\":\"OnlyCoordinatorCanFulfill\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"have\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"coordinator\",\"type\":\"address\"}],\"name\":\"OnlyOwnerOrCoordinator\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"SubscriptionIdMissing\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"wrapperGasOverhead\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"coordinatorGasOverhead\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"coordinatorNativePremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"coordinatorLinkPremiumPercentage\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint8\",\"name\":\"maxNumWords\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"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\"}],\"name\":\"ConfigSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vrfCoordinator\",\"type\":\"address\"}],\"name\":\"CoordinatorSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Disabled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"Enabled\",\"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\":\"uint32\",\"name\":\"size\",\"type\":\"uint32\"}],\"name\":\"FulfillmentTxSizeSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"NativeWithdrawn\",\"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\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"consumer\",\"type\":\"address\"}],\"name\":\"WrapperFulfillmentFailed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SUBSCRIPTION_ID\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"calculateRequestPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"}],\"name\":\"calculateRequestPriceNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isLinkMode\",\"type\":\"bool\"}],\"name\":\"checkPaymentMode\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"disable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"enable\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"_requestGasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateRequestPrice\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint256\",\"name\":\"_requestGasPriceWei\",\"type\":\"uint256\"}],\"name\":\"estimateRequestPriceNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConfig\",\"outputs\":[{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"wrapperGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"coordinatorGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"wrapperNativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"wrapperLinkPremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"maxNumWords\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastRequestId\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"link\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"linkNativeFeed\",\"outputs\":[{\"internalType\":\"address\",\"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\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"},{\"internalType\":\"uint256[]\",\"name\":\"randomWords\",\"type\":\"uint256[]\"}],\"name\":\"rawFulfillRandomWords\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint16\",\"name\":\"_requestConfirmations\",\"type\":\"uint16\"},{\"internalType\":\"uint32\",\"name\":\"_numWords\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"extraArgs\",\"type\":\"bytes\"}],\"name\":\"requestRandomWordsInNative\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"requestId\",\"type\":\"uint256\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"s_callbacks\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"callbackAddress\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"callbackGasLimit\",\"type\":\"uint32\"},{\"internalType\":\"uint64\",\"name\":\"requestGasPrice\",\"type\":\"uint64\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_configured\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_disabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_fulfillmentTxSizeBytes\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_vrfCoordinator\",\"outputs\":[{\"internalType\":\"contractIVRFCoordinatorV2Plus\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"_wrapperGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_coordinatorGasOverhead\",\"type\":\"uint32\"},{\"internalType\":\"uint8\",\"name\":\"_coordinatorNativePremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"_coordinatorLinkPremiumPercentage\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"_keyHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint8\",\"name\":\"_maxNumWords\",\"type\":\"uint8\"},{\"internalType\":\"uint32\",\"name\":\"_stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"_fallbackWeiPerUnitLink\",\"type\":\"int256\"},{\"internalType\":\"uint32\",\"name\":\"_fulfillmentFlatFeeNativePPM\",\"type\":\"uint32\"},{\"internalType\":\"uint32\",\"name\":\"_fulfillmentFlatFeeLinkDiscountPPM\",\"type\":\"uint32\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_vrfCoordinator\",\"type\":\"address\"}],\"name\":\"setCoordinator\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"size\",\"type\":\"uint32\"}],\"name\":\"setFulfillmentTxSize\",\"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\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"}],\"name\":\"withdrawNative\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x60e06040526006805463ffffffff60401b191669024400000000000000001790553480156200002d57600080fd5b5060405162003c1c38038062003c1c8339810160408190526200005091620002a1565b813380600081620000a85760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000db57620000db81620001d9565b5050506001600160a01b038116620001065760405163d92e233d60e01b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392831617905584811660a052831660c0526000819003620001505760405163a81c0bef60e01b815260040160405180910390fd5b60025460405163dc311dd360e01b8152600481018390526001600160a01b039091169063dc311dd390602401600060405180830381865afa1580156200019a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620001c4919081019062000321565b505050608092909252506200044a9350505050565b336001600160a01b03821603620002335760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016200009f565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b80516001600160a01b03811681146200029c57600080fd5b919050565b60008060008060808587031215620002b857600080fd5b620002c38562000284565b9350620002d36020860162000284565b9250620002e36040860162000284565b6060959095015193969295505050565b80516001600160601b03811681146200029c57600080fd5b634e487b7160e01b600052604160045260246000fd5b600080600080600060a086880312156200033a57600080fd5b6200034586620002f3565b9450602062000356818801620002f3565b60408801519095506001600160401b0380821682146200037557600080fd5b8195506200038660608a0162000284565b945060808901519150808211156200039d57600080fd5b818901915089601f830112620003b257600080fd5b815181811115620003c757620003c76200030b565b8060051b604051601f19603f83011681018181108582111715620003ef57620003ef6200030b565b60405291825284820192508381018501918c8311156200040e57600080fd5b938501935b828510156200043757620004278562000284565b8452938501939285019262000413565b8096505050505050509295509295909350565b60805160a05160c051613778620004a4600039600081816102ff015261260601526000818161028b01528181610f1b01528181610fea0152611ac60152600081816101d90152818161171b0152611cb201526137786000f3fe6080604052600436106101c25760003560e01c806379ba5097116100f7578063a4c0ed3611610095578063cdd8d88511610064578063cdd8d88514610738578063f2fde38b14610776578063fc2a88c314610796578063fc2dbebc146107ac57600080fd5b8063a4c0ed36146105ba578063a608a1e1146105da578063bf17e5591461060d578063c3f909d41461062d57600080fd5b80638ea98117116100d15780638ea98117146105455780639cfc058e146105655780639eccacf614610578578063a3907d71146105a557600080fd5b806379ba5097146104e55780637fb5d19d146104fa5780638da5cb5b1461051a57600080fd5b80632f622e6b1161016457806348baa1c51161013e57806348baa1c5146103985780634b1609351461046357806351cff8d91461048357806357a8070a146104a357600080fd5b80632f622e6b146103385780633255c456146103585780634306d3541461037857600080fd5b80631c4695f4116101a05780631c4695f41461027c5780631fe543e3146102d05780632808e6c8146102f05780632f2770db1461032357600080fd5b8063030932bb146101c7578063181f5a771461020e57806318b6f4c81461025a575b600080fd5b3480156101d357600080fd5b506101fb7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b34801561021a57600080fd5b50604080518082018252601281527f56524656325772617070657220312e302e300000000000000000000000000000602082015290516102059190612e0f565b34801561026657600080fd5b5061027a610275366004612f3c565b6107cc565b005b34801561028857600080fd5b507f00000000000000000000000000000000000000000000000000000000000000005b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610205565b3480156102dc57600080fd5b5061027a6102eb366004612f8e565b610954565b3480156102fc57600080fd5b507f00000000000000000000000000000000000000000000000000000000000000006102ab565b34801561032f57600080fd5b5061027a6109d1565b34801561034457600080fd5b5061027a610353366004613064565b610a44565b34801561036457600080fd5b506101fb610373366004613093565b610b6b565b34801561038457600080fd5b506101fb6103933660046130bd565b610c91565b3480156103a457600080fd5b506104226103b33660046130d8565b60076020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff81169074010000000000000000000000000000000000000000810463ffffffff16907801000000000000000000000000000000000000000000000000900467ffffffffffffffff1683565b6040805173ffffffffffffffffffffffffffffffffffffffff909416845263ffffffff909216602084015267ffffffffffffffff1690820152606001610205565b34801561046f57600080fd5b506101fb61047e3660046130bd565b610dc5565b34801561048f57600080fd5b5061027a61049e366004613064565b610ee2565b3480156104af57600080fd5b506002546104d59074010000000000000000000000000000000000000000900460ff1681565b6040519015158152602001610205565b3480156104f157600080fd5b5061027a6110e3565b34801561050657600080fd5b506101fb610515366004613093565b6111e0565b34801561052657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff166102ab565b34801561055157600080fd5b5061027a610560366004613064565b611313565b6101fb61057336600461314c565b61149e565b34801561058457600080fd5b506002546102ab9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105b157600080fd5b5061027a611949565b3480156105c657600080fd5b5061027a6105d53660046131c2565b6119a4565b3480156105e657600080fd5b506002546104d5907501000000000000000000000000000000000000000000900460ff1681565b34801561061957600080fd5b5061027a6106283660046130bd565b611f11565b34801561063957600080fd5b506005546006546003546002546040805194855263ffffffff80851660208701527001000000000000000000000000000000008504811691860191909152740100000000000000000000000000000000000000008404811660608601526401000000008404811660808601526c0100000000000000000000000084041660a085015260ff78010000000000000000000000000000000000000000000000008404811660c0860152790100000000000000000000000000000000000000000000000000909304831660e085015261010084019190915276010000000000000000000000000000000000000000000090041661012082015261014001610205565b34801561074457600080fd5b506006546107619068010000000000000000900463ffffffff1681565b60405163ffffffff9091168152602001610205565b34801561078257600080fd5b5061027a610791366004613064565b611f8a565b3480156107a257600080fd5b506101fb60045481565b3480156107b857600080fd5b5061027a6107c736600461322d565b611f9e565b8151600003610810578061080c576040517f6b81746e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5050565b81516024111561086a5781516040517f51200dce0000000000000000000000000000000000000000000000000000000081526108619160249160040161ffff92831681529116602082015260400190565b60405180910390fd5b60008260238151811061087f5761087f6132d9565b6020910101517fff00000000000000000000000000000000000000000000000000000000000000167f01000000000000000000000000000000000000000000000000000000000000001490508080156108d55750815b1561090c576040517f6048aa6800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80158015610918575081155b1561094f576040517f6b81746e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60025473ffffffffffffffffffffffffffffffffffffffff1633146109c7576002546040517f1cf993f400000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091166024820152604401610861565b61080c828261226f565b6109d9612452565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1675010000000000000000000000000000000000000000001790556040517f75884cdadc4a89e8b545db800057f06ec7f5338a08183c7ba515f2bfdd9fe1e190600090a1565b610a4c612452565b604051479060009073ffffffffffffffffffffffffffffffffffffffff84169083908381818185875af1925050503d8060008114610aa6576040519150601f19603f3d011682016040523d82523d6000602084013e610aab565b606091505b5050905080610b16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f6661696c656420746f207769746864726177206e6174697665000000000000006044820152606401610861565b8273ffffffffffffffffffffffffffffffffffffffff167fc303ca808382409472acbbf899c316cf439f409f6584aae22df86dfa3c9ed50483604051610b5e91815260200190565b60405180910390a2505050565b60025460009074010000000000000000000000000000000000000000900460ff16610bf2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff1615610c78576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b610c888363ffffffff16836124d5565b90505b92915050565b60025460009074010000000000000000000000000000000000000000900460ff16610d18576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff1615610d9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b6000610da86125e8565b509050610dbc8363ffffffff163a8361273e565b9150505b919050565b60025460009074010000000000000000000000000000000000000000900460ff16610e4c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff1615610ed2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b610c8b8263ffffffff163a6124d5565b610eea612452565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9b9190613308565b6040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152602482018390529192507f00000000000000000000000000000000000000000000000000000000000000009091169063a9059cbb906044016020604051808303816000875af1158015611035573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110599190613321565b61108f576040517f7c07fc4c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff167f7084f5476618d8e60b11ef0d7d3f06914655adb8793e28ff7f018d4c76d505d5826040516110d791815260200190565b60405180910390a25050565b60015473ffffffffffffffffffffffffffffffffffffffff163314611164576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e6572000000000000000000006044820152606401610861565b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b60025460009074010000000000000000000000000000000000000000900460ff16611267576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff16156112ed576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b60006112f76125e8565b50905061130b8463ffffffff16848361273e565b949350505050565b60005473ffffffffffffffffffffffffffffffffffffffff163314801590611353575060025473ffffffffffffffffffffffffffffffffffffffff163314155b156113d7573361137860005473ffffffffffffffffffffffffffffffffffffffff1690565b6002546040517f061db9c100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff93841660048201529183166024830152919091166044820152606401610861565b73ffffffffffffffffffffffffffffffffffffffff8116611424576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081179091556040519081527fd1a6a14209a385a964d036e404cb5cfb71f4000cdb03c9366292430787261be6906020015b60405180910390a150565b60025460009074010000000000000000000000000000000000000000900460ff16611525576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff16156115ab576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b6115ea83838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525092506107cc915050565b60006115f58761289a565b905060006116098863ffffffff163a6124d5565b905080341015611675576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f770000000000000000000000000000000000000000006044820152606401610861565b600254760100000000000000000000000000000000000000000000900460ff1663ffffffff87161115611704576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f20686967680000000000000000000000000000006044820152606401610861565b60006040518060c0016040528060035481526020017f000000000000000000000000000000000000000000000000000000000000000081526020018961ffff168152602001600660049054906101000a900463ffffffff16858c6117689190613374565b6117729190613374565b63ffffffff1681526020018863ffffffff16815260200187878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050509152506002546040517f9b1c385e00000000000000000000000000000000000000000000000000000000815291925073ffffffffffffffffffffffffffffffffffffffff1690639b1c385e90611818908490600401613398565b6020604051808303816000875af1158015611837573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061185b9190613308565b6040805160608101825233815263ffffffff808d16602080840191825267ffffffffffffffff3a81168587019081526000888152600790935295909120935184549251955190911678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff9590931674010000000000000000000000000000000000000000027fffffffffffffffff00000000000000000000000000000000000000000000000090921673ffffffffffffffffffffffffffffffffffffffff91909116171792909216919091179055935050505095945050505050565b611951612452565b600280547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff1690556040517fc0f961051f97b04c496472d11cb6170d844e4b2c9dfd3b602a4fa0139712d48490600090a1565b60025474010000000000000000000000000000000000000000900460ff16611a28576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f77726170706572206973206e6f7420636f6e66696775726564000000000000006044820152606401610861565b6002547501000000000000000000000000000000000000000000900460ff1615611aae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f777261707065722069732064697361626c6564000000000000000000000000006044820152606401610861565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614611b4d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c792063616c6c61626c652066726f6d204c494e4b0000000000000000006044820152606401610861565b6000808080611b5e858701876133f5565b9350935093509350611b718160016107cc565b6000611b7c8561289a565b9050600080611b896125e8565b915091506000611ba08863ffffffff163a8561273e565b9050808b1015611c0c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f66656520746f6f206c6f770000000000000000000000000000000000000000006044820152606401610861565b600254760100000000000000000000000000000000000000000000900460ff1663ffffffff87161115611c9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f6e756d576f72647320746f6f20686967680000000000000000000000000000006044820152606401610861565b60006040518060c0016040528060035481526020017f000000000000000000000000000000000000000000000000000000000000000081526020018961ffff168152602001600660049054906101000a900463ffffffff16878c611cff9190613374565b611d099190613374565b63ffffffff908116825289166020820152604090810188905260025490517f9b1c385e00000000000000000000000000000000000000000000000000000000815291925060009173ffffffffffffffffffffffffffffffffffffffff90911690639b1c385e90611d7d908590600401613398565b6020604051808303816000875af1158015611d9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc09190613308565b905060405180606001604052808f73ffffffffffffffffffffffffffffffffffffffff1681526020018b63ffffffff1681526020013a67ffffffffffffffff168152506007600083815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160186101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550905050806004819055508315611f01576005546040805183815260208101929092527f6ca648a381f22ead7e37773d934e64885dcf861fbfbb26c40354cbf0c4662d1a910160405180910390a15b5050505050505050505050505050565b611f19612452565b600680547fffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffff166801000000000000000063ffffffff8416908102919091179091556040519081527f697b48b8b76cebb09a54ec4ff810e8a181c96f65395d51c744db09c115d1d5d090602001611493565b611f92612452565b611f9b816128b2565b50565b611fa6612452565b8163ffffffff168163ffffffff161115611ffc576040517f2780dcb200000000000000000000000000000000000000000000000000000000815263ffffffff808316600483015283166024820152604401610861565b609b60ff89161115612046576040517f3acc511a00000000000000000000000000000000000000000000000000000000815260ff89166004820152609b6024820152604401610861565b609b60ff88161115612090576040517f3acc511a00000000000000000000000000000000000000000000000000000000815260ff88166004820152609b6024820152604401610861565b89600660046101000a81548163ffffffff021916908363ffffffff160217905550886006600c6101000a81548163ffffffff021916908363ffffffff16021790555087600660186101000a81548160ff021916908360ff16021790555086600660196101000a81548160ff021916908360ff1602179055508560038190555084600260166101000a81548160ff021916908360ff1602179055506001600260146101000a81548160ff02191690831515021790555083600660006101000a81548163ffffffff021916908363ffffffff1602179055508260058190555081600660106101000a81548163ffffffff021916908363ffffffff16021790555080600660146101000a81548163ffffffff021916908363ffffffff1602179055507fb18fd84519589131d50ae195b0aea1b042c3c0b25a53bb894d9d81c78980c20f8a8a8a8a8a8a8a8a8a600660149054906101000a900463ffffffff1660405161225b9a9998979695949392919063ffffffff9a8b168152988a1660208a015260ff97881660408a0152958716606089015260808801949094529190941660a086015292851660c085015260e08401929092529083166101008301529091166101208201526101400190565b60405180910390a150505050505050505050565b60008281526007602081815260408084208151606081018352815473ffffffffffffffffffffffffffffffffffffffff808216835274010000000000000000000000000000000000000000820463ffffffff1683870152780100000000000000000000000000000000000000000000000090910467ffffffffffffffff16938201939093528786529390925292905580519091811661236a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f72657175657374206e6f7420666f756e640000000000000000000000000000006044820152606401610861565b600080631fe543e360e01b8686604051602401612388929190613464565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060006123fe856020015163ffffffff1685846129a7565b9050806124495760405173ffffffffffffffffffffffffffffffffffffffff85169088907fc551b83c151f2d1c7eeb938ac59008e0409f1c1dc1e2f112449d4d79b458902290600090a35b50505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146124d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e6572000000000000000000006044820152606401610861565b565b60065460009081906124f590640100000000900463ffffffff16846134b2565b6006549091506000906125199068010000000000000000900463ffffffff166129f3565b60065461253c906c01000000000000000000000000900463ffffffff16876134c9565b61254690866134b2565b61255091906134c9565b60065490915060009061258290700100000000000000000000000000000000900463ffffffff1664e8d4a510006134b2565b6006546064906125b1907801000000000000000000000000000000000000000000000000900460ff16826134dc565b6125be9060ff16856134b2565b6125c89190613524565b6125d291906134c9565b90506125de81846134c9565b9695505050505050565b6000806000600660009054906101000a900463ffffffff16905060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663feaf968c6040518163ffffffff1660e01b815260040160a060405180830381865afa15801561266f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126939190613552565b50919650909250505063ffffffff8216158015906126bf57506126b681426135a2565b8263ffffffff16105b925082156126cd5760055493505b6000841215612738576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e76616c6964204c494e4b20776569207072696365000000000000000000006044820152606401610861565b50509091565b600654600090819061275e90640100000000900463ffffffff16856134b2565b6006549091506000906127829068010000000000000000900463ffffffff166129f3565b6006546127a5906c01000000000000000000000000900463ffffffff16886134c9565b6127af90876134b2565b6127b991906134c9565b6006549091506000906128009063ffffffff7401000000000000000000000000000000000000000082048116917001000000000000000000000000000000009004166135b5565b6128159063ffffffff1664e8d4a510006134b2565b60065460649061284590790100000000000000000000000000000000000000000000000000900460ff16826134dc565b6128529060ff16856134b2565b61285c9190613524565b61286691906134c9565b90508461287382856134c9565b61288590670de0b6b3a76400006134b2565b61288f9190613524565b979650505050505050565b60006128a7603f836135d2565b610c8b906001613374565b3373ffffffffffffffffffffffffffffffffffffffff821603612931576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c660000000000000000006044820152606401610861565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60005a6113888110156129b957600080fd5b6113888103905084604082048203116129d157600080fd5b50823b6129dd57600080fd5b60008083516020850160008789f1949350505050565b6000466129ff81612ab4565b15612a94576000606c73ffffffffffffffffffffffffffffffffffffffff166341b247a86040518163ffffffff1660e01b815260040160c060405180830381865afa158015612a52573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a7691906135f5565b5050505091505083608c612a8a91906134c9565b61130b90826134b2565b612a9d81612ad7565b15612aab57610dbc83612b11565b50600092915050565b600061a4b1821480612ac8575062066eed82145b80610c8b57505062066eee1490565b6000600a821480612ae957506101a482145b80612af6575062aa37dc82145b80612b02575061210582145b80610c8b57505062014a331490565b60008073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663519b4bd36040518163ffffffff1660e01b8152600401602060405180830381865afa158015612b73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b979190613308565b9050600080612ba681866135a2565b90506000612bb58260106134b2565b612bc08460046134b2565b612bca91906134c9565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff16630c18c1626040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c2d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c519190613308565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663f45e65d86040518163ffffffff1660e01b8152600401602060405180830381865afa158015612cb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612cd89190613308565b9050600073420000000000000000000000000000000000000f73ffffffffffffffffffffffffffffffffffffffff1663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015612d3b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d5f9190613308565b90506000612d6e82600a61375f565b905060008184612d7e87896134c9565b612d88908c6134b2565b612d9291906134b2565b612d9c9190613524565b9b9a5050505050505050505050565b6000815180845260005b81811015612dd157602081850181015186830182015201612db5565b5060006020828601015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011685010191505092915050565b602081526000610c886020830184612dab565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612e9857612e98612e22565b604052919050565b600082601f830112612eb157600080fd5b813567ffffffffffffffff811115612ecb57612ecb612e22565b612efc60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612e51565b818152846020838601011115612f1157600080fd5b816020850160208301376000918101602001919091529392505050565b8015158114611f9b57600080fd5b60008060408385031215612f4f57600080fd5b823567ffffffffffffffff811115612f6657600080fd5b612f7285828601612ea0565b9250506020830135612f8381612f2e565b809150509250929050565b60008060408385031215612fa157600080fd5b8235915060208084013567ffffffffffffffff80821115612fc157600080fd5b818601915086601f830112612fd557600080fd5b813581811115612fe757612fe7612e22565b8060051b9150612ff8848301612e51565b818152918301840191848101908984111561301257600080fd5b938501935b8385101561303057843582529385019390850190613017565b8096505050505050509250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610dc057600080fd5b60006020828403121561307657600080fd5b610c8882613040565b803563ffffffff81168114610dc057600080fd5b600080604083850312156130a657600080fd5b6130af8361307f565b946020939093013593505050565b6000602082840312156130cf57600080fd5b610c888261307f565b6000602082840312156130ea57600080fd5b5035919050565b803561ffff81168114610dc057600080fd5b60008083601f84011261311557600080fd5b50813567ffffffffffffffff81111561312d57600080fd5b60208301915083602082850101111561314557600080fd5b9250929050565b60008060008060006080868803121561316457600080fd5b61316d8661307f565b945061317b602087016130f1565b93506131896040870161307f565b9250606086013567ffffffffffffffff8111156131a557600080fd5b6131b188828901613103565b969995985093965092949392505050565b600080600080606085870312156131d857600080fd5b6131e185613040565b935060208501359250604085013567ffffffffffffffff81111561320457600080fd5b61321087828801613103565b95989497509550505050565b803560ff81168114610dc057600080fd5b6000806000806000806000806000806101408b8d03121561324d57600080fd5b6132568b61307f565b995061326460208c0161307f565b985061327260408c0161321c565b975061328060608c0161321c565b965060808b0135955061329560a08c0161321c565b94506132a360c08c0161307f565b935060e08b013592506132b96101008c0161307f565b91506132c86101208c0161307f565b90509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60006020828403121561331a57600080fd5b5051919050565b60006020828403121561333357600080fd5b815161333e81612f2e565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b63ffffffff81811683821601908082111561339157613391613345565b5092915050565b60208152815160208201526020820151604082015261ffff60408301511660608201526000606083015163ffffffff80821660808501528060808601511660a0850152505060a083015160c08084015261130b60e0840182612dab565b6000806000806080858703121561340b57600080fd5b6134148561307f565b9350613422602086016130f1565b92506134306040860161307f565b9150606085013567ffffffffffffffff81111561344c57600080fd5b61345887828801612ea0565b91505092959194509250565b6000604082018483526020604081850152818551808452606086019150828701935060005b818110156134a557845183529383019391830191600101613489565b5090979650505050505050565b8082028115828204841417610c8b57610c8b613345565b80820180821115610c8b57610c8b613345565b60ff8181168382160190811115610c8b57610c8b613345565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082613533576135336134f5565b500490565b805169ffffffffffffffffffff81168114610dc057600080fd5b600080600080600060a0868803121561356a57600080fd5b61357386613538565b945060208601519350604086015192506060860151915061359660808701613538565b90509295509295909350565b81810381811115610c8b57610c8b613345565b63ffffffff82811682821603908082111561339157613391613345565b600063ffffffff808416806135e9576135e96134f5565b92169190910492915050565b60008060008060008060c0878903121561360e57600080fd5b865195506020870151945060408701519350606087015192506080870151915060a087015190509295509295509295565b600181815b8085111561369857817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561367e5761367e613345565b8085161561368b57918102915b93841c9390800290613644565b509250929050565b6000826136af57506001610c8b565b816136bc57506000610c8b565b81600181146136d257600281146136dc576136f8565b6001915050610c8b565b60ff8411156136ed576136ed613345565b50506001821b610c8b565b5060208310610133831016604e8410600b841016171561371b575081810a610c8b565b613725838361363f565b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0482111561375757613757613345565b029392505050565b6000610c8883836136a056fea164736f6c6343000813000a", } var VRFV2PlusWrapperABI = VRFV2PlusWrapperMetaData.ABI @@ -383,6 +383,28 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapperCallerSession) Link() (common.Address, return _VRFV2PlusWrapper.Contract.Link(&_VRFV2PlusWrapper.CallOpts) } +func (_VRFV2PlusWrapper *VRFV2PlusWrapperCaller) LinkNativeFeed(opts *bind.CallOpts) (common.Address, error) { + var out []interface{} + err := _VRFV2PlusWrapper.contract.Call(opts, &out, "linkNativeFeed") + + if err != nil { + return *new(common.Address), err + } + + out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) + + return out0, err + +} + +func (_VRFV2PlusWrapper *VRFV2PlusWrapperSession) LinkNativeFeed() (common.Address, error) { + return _VRFV2PlusWrapper.Contract.LinkNativeFeed(&_VRFV2PlusWrapper.CallOpts) +} + +func (_VRFV2PlusWrapper *VRFV2PlusWrapperCallerSession) LinkNativeFeed() (common.Address, error) { + return _VRFV2PlusWrapper.Contract.LinkNativeFeed(&_VRFV2PlusWrapper.CallOpts) +} + func (_VRFV2PlusWrapper *VRFV2PlusWrapperCaller) Owner(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _VRFV2PlusWrapper.contract.Call(opts, &out, "owner") @@ -502,28 +524,6 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapperCallerSession) SFulfillmentTxSizeBytes( return _VRFV2PlusWrapper.Contract.SFulfillmentTxSizeBytes(&_VRFV2PlusWrapper.CallOpts) } -func (_VRFV2PlusWrapper *VRFV2PlusWrapperCaller) SLinkNativeFeed(opts *bind.CallOpts) (common.Address, error) { - var out []interface{} - err := _VRFV2PlusWrapper.contract.Call(opts, &out, "s_linkNativeFeed") - - if err != nil { - return *new(common.Address), err - } - - out0 := *abi.ConvertType(out[0], new(common.Address)).(*common.Address) - - return out0, err - -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperSession) SLinkNativeFeed() (common.Address, error) { - return _VRFV2PlusWrapper.Contract.SLinkNativeFeed(&_VRFV2PlusWrapper.CallOpts) -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperCallerSession) SLinkNativeFeed() (common.Address, error) { - return _VRFV2PlusWrapper.Contract.SLinkNativeFeed(&_VRFV2PlusWrapper.CallOpts) -} - func (_VRFV2PlusWrapper *VRFV2PlusWrapperCaller) SVrfCoordinator(opts *bind.CallOpts) (common.Address, error) { var out []interface{} err := _VRFV2PlusWrapper.contract.Call(opts, &out, "s_vrfCoordinator") @@ -640,16 +640,16 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactorSession) RequestRandomWordsIn return _VRFV2PlusWrapper.Contract.RequestRandomWordsInNative(&_VRFV2PlusWrapper.TransactOpts, _callbackGasLimit, _requestConfirmations, _numWords, extraArgs) } -func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactor) SetConfig(opts *bind.TransactOpts, _wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _wrapperNativePremiumPercentage uint8, _wrapperLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { - return _VRFV2PlusWrapper.contract.Transact(opts, "setConfig", _wrapperGasOverhead, _coordinatorGasOverhead, _wrapperNativePremiumPercentage, _wrapperLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) +func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactor) SetConfig(opts *bind.TransactOpts, _wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _coordinatorNativePremiumPercentage uint8, _coordinatorLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { + return _VRFV2PlusWrapper.contract.Transact(opts, "setConfig", _wrapperGasOverhead, _coordinatorGasOverhead, _coordinatorNativePremiumPercentage, _coordinatorLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) } -func (_VRFV2PlusWrapper *VRFV2PlusWrapperSession) SetConfig(_wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _wrapperNativePremiumPercentage uint8, _wrapperLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { - return _VRFV2PlusWrapper.Contract.SetConfig(&_VRFV2PlusWrapper.TransactOpts, _wrapperGasOverhead, _coordinatorGasOverhead, _wrapperNativePremiumPercentage, _wrapperLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) +func (_VRFV2PlusWrapper *VRFV2PlusWrapperSession) SetConfig(_wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _coordinatorNativePremiumPercentage uint8, _coordinatorLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { + return _VRFV2PlusWrapper.Contract.SetConfig(&_VRFV2PlusWrapper.TransactOpts, _wrapperGasOverhead, _coordinatorGasOverhead, _coordinatorNativePremiumPercentage, _coordinatorLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) } -func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactorSession) SetConfig(_wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _wrapperNativePremiumPercentage uint8, _wrapperLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { - return _VRFV2PlusWrapper.Contract.SetConfig(&_VRFV2PlusWrapper.TransactOpts, _wrapperGasOverhead, _coordinatorGasOverhead, _wrapperNativePremiumPercentage, _wrapperLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) +func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactorSession) SetConfig(_wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _coordinatorNativePremiumPercentage uint8, _coordinatorLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) { + return _VRFV2PlusWrapper.Contract.SetConfig(&_VRFV2PlusWrapper.TransactOpts, _wrapperGasOverhead, _coordinatorGasOverhead, _coordinatorNativePremiumPercentage, _coordinatorLinkPremiumPercentage, _keyHash, _maxNumWords, _stalenessSeconds, _fallbackWeiPerUnitLink, _fulfillmentFlatFeeNativePPM, _fulfillmentFlatFeeLinkDiscountPPM) } func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactor) SetCoordinator(opts *bind.TransactOpts, _vrfCoordinator common.Address) (*types.Transaction, error) { @@ -676,18 +676,6 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactorSession) SetFulfillmentTxSize return _VRFV2PlusWrapper.Contract.SetFulfillmentTxSize(&_VRFV2PlusWrapper.TransactOpts, size) } -func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactor) SetLinkNativeFeed(opts *bind.TransactOpts, linkNativeFeed common.Address) (*types.Transaction, error) { - return _VRFV2PlusWrapper.contract.Transact(opts, "setLinkNativeFeed", linkNativeFeed) -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperSession) SetLinkNativeFeed(linkNativeFeed common.Address) (*types.Transaction, error) { - return _VRFV2PlusWrapper.Contract.SetLinkNativeFeed(&_VRFV2PlusWrapper.TransactOpts, linkNativeFeed) -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactorSession) SetLinkNativeFeed(linkNativeFeed common.Address) (*types.Transaction, error) { - return _VRFV2PlusWrapper.Contract.SetLinkNativeFeed(&_VRFV2PlusWrapper.TransactOpts, linkNativeFeed) -} - func (_VRFV2PlusWrapper *VRFV2PlusWrapperTransactor) TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) { return _VRFV2PlusWrapper.contract.Transact(opts, "transferOwnership", to) } @@ -785,17 +773,17 @@ func (it *VRFV2PlusWrapperConfigSetIterator) Close() error { } type VRFV2PlusWrapperConfigSet struct { - WrapperGasOverhead uint32 - CoordinatorGasOverhead uint32 - WrapperNativePremiumPercentage uint8 - WrapperLinkPremiumPercentage uint8 - KeyHash [32]byte - MaxNumWords uint8 - StalenessSeconds uint32 - FallbackWeiPerUnitLink *big.Int - FulfillmentFlatFeeNativePPM uint32 - FulfillmentFlatFeeLinkDiscountPPM uint32 - Raw types.Log + WrapperGasOverhead uint32 + CoordinatorGasOverhead uint32 + CoordinatorNativePremiumPercentage uint8 + CoordinatorLinkPremiumPercentage uint8 + KeyHash [32]byte + MaxNumWords uint8 + StalenessSeconds uint32 + FallbackWeiPerUnitLink *big.Int + FulfillmentFlatFeeNativePPM uint32 + FulfillmentFlatFeeLinkDiscountPPM uint32 + Raw types.Log } func (_VRFV2PlusWrapper *VRFV2PlusWrapperFilterer) FilterConfigSet(opts *bind.FilterOpts) (*VRFV2PlusWrapperConfigSetIterator, error) { @@ -1434,123 +1422,6 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapperFilterer) ParseFulfillmentTxSizeSet(log return event, nil } -type VRFV2PlusWrapperLinkNativeFeedSetIterator struct { - Event *VRFV2PlusWrapperLinkNativeFeedSet - - contract *bind.BoundContract - event string - - logs chan types.Log - sub ethereum.Subscription - done bool - fail error -} - -func (it *VRFV2PlusWrapperLinkNativeFeedSetIterator) Next() bool { - - if it.fail != nil { - return false - } - - if it.done { - select { - case log := <-it.logs: - it.Event = new(VRFV2PlusWrapperLinkNativeFeedSet) - 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(VRFV2PlusWrapperLinkNativeFeedSet) - 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 *VRFV2PlusWrapperLinkNativeFeedSetIterator) Error() error { - return it.fail -} - -func (it *VRFV2PlusWrapperLinkNativeFeedSetIterator) Close() error { - it.sub.Unsubscribe() - return nil -} - -type VRFV2PlusWrapperLinkNativeFeedSet struct { - LinkNativeFeed common.Address - Raw types.Log -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperFilterer) FilterLinkNativeFeedSet(opts *bind.FilterOpts) (*VRFV2PlusWrapperLinkNativeFeedSetIterator, error) { - - logs, sub, err := _VRFV2PlusWrapper.contract.FilterLogs(opts, "LinkNativeFeedSet") - if err != nil { - return nil, err - } - return &VRFV2PlusWrapperLinkNativeFeedSetIterator{contract: _VRFV2PlusWrapper.contract, event: "LinkNativeFeedSet", logs: logs, sub: sub}, nil -} - -func (_VRFV2PlusWrapper *VRFV2PlusWrapperFilterer) WatchLinkNativeFeedSet(opts *bind.WatchOpts, sink chan<- *VRFV2PlusWrapperLinkNativeFeedSet) (event.Subscription, error) { - - logs, sub, err := _VRFV2PlusWrapper.contract.WatchLogs(opts, "LinkNativeFeedSet") - if err != nil { - return nil, err - } - return event.NewSubscription(func(quit <-chan struct{}) error { - defer sub.Unsubscribe() - for { - select { - case log := <-logs: - - event := new(VRFV2PlusWrapperLinkNativeFeedSet) - if err := _VRFV2PlusWrapper.contract.UnpackLog(event, "LinkNativeFeedSet", 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 (_VRFV2PlusWrapper *VRFV2PlusWrapperFilterer) ParseLinkNativeFeedSet(log types.Log) (*VRFV2PlusWrapperLinkNativeFeedSet, error) { - event := new(VRFV2PlusWrapperLinkNativeFeedSet) - if err := _VRFV2PlusWrapper.contract.UnpackLog(event, "LinkNativeFeedSet", log); err != nil { - return nil, err - } - event.Raw = log - return event, nil -} - type VRFV2PlusWrapperNativeWithdrawnIterator struct { Event *VRFV2PlusWrapperNativeWithdrawn @@ -2247,8 +2118,6 @@ func (_VRFV2PlusWrapper *VRFV2PlusWrapper) ParseLog(log types.Log) (generated.Ab return _VRFV2PlusWrapper.ParseFallbackWeiPerUnitLinkUsed(log) case _VRFV2PlusWrapper.abi.Events["FulfillmentTxSizeSet"].ID: return _VRFV2PlusWrapper.ParseFulfillmentTxSizeSet(log) - case _VRFV2PlusWrapper.abi.Events["LinkNativeFeedSet"].ID: - return _VRFV2PlusWrapper.ParseLinkNativeFeedSet(log) case _VRFV2PlusWrapper.abi.Events["NativeWithdrawn"].ID: return _VRFV2PlusWrapper.ParseNativeWithdrawn(log) case _VRFV2PlusWrapper.abi.Events["OwnershipTransferRequested"].ID: @@ -2289,10 +2158,6 @@ func (VRFV2PlusWrapperFulfillmentTxSizeSet) Topic() common.Hash { return common.HexToHash("0x697b48b8b76cebb09a54ec4ff810e8a181c96f65395d51c744db09c115d1d5d0") } -func (VRFV2PlusWrapperLinkNativeFeedSet) Topic() common.Hash { - return common.HexToHash("0xc252955f9bd8c6ea6e3cc712bbad31005d85cec90e73b147b4d6e8326242efdf") -} - func (VRFV2PlusWrapperNativeWithdrawn) Topic() common.Hash { return common.HexToHash("0xc303ca808382409472acbbf899c316cf439f409f6584aae22df86dfa3c9ed504") } @@ -2338,6 +2203,8 @@ type VRFV2PlusWrapperInterface interface { Link(opts *bind.CallOpts) (common.Address, error) + LinkNativeFeed(opts *bind.CallOpts) (common.Address, error) + Owner(opts *bind.CallOpts) (common.Address, error) SCallbacks(opts *bind.CallOpts, arg0 *big.Int) (SCallbacks, @@ -2350,8 +2217,6 @@ type VRFV2PlusWrapperInterface interface { SFulfillmentTxSizeBytes(opts *bind.CallOpts) (uint32, error) - SLinkNativeFeed(opts *bind.CallOpts) (common.Address, error) - SVrfCoordinator(opts *bind.CallOpts) (common.Address, error) TypeAndVersion(opts *bind.CallOpts) (string, error) @@ -2368,14 +2233,12 @@ type VRFV2PlusWrapperInterface interface { RequestRandomWordsInNative(opts *bind.TransactOpts, _callbackGasLimit uint32, _requestConfirmations uint16, _numWords uint32, extraArgs []byte) (*types.Transaction, error) - SetConfig(opts *bind.TransactOpts, _wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _wrapperNativePremiumPercentage uint8, _wrapperLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) + SetConfig(opts *bind.TransactOpts, _wrapperGasOverhead uint32, _coordinatorGasOverhead uint32, _coordinatorNativePremiumPercentage uint8, _coordinatorLinkPremiumPercentage uint8, _keyHash [32]byte, _maxNumWords uint8, _stalenessSeconds uint32, _fallbackWeiPerUnitLink *big.Int, _fulfillmentFlatFeeNativePPM uint32, _fulfillmentFlatFeeLinkDiscountPPM uint32) (*types.Transaction, error) SetCoordinator(opts *bind.TransactOpts, _vrfCoordinator common.Address) (*types.Transaction, error) SetFulfillmentTxSize(opts *bind.TransactOpts, size uint32) (*types.Transaction, error) - SetLinkNativeFeed(opts *bind.TransactOpts, linkNativeFeed common.Address) (*types.Transaction, error) - TransferOwnership(opts *bind.TransactOpts, to common.Address) (*types.Transaction, error) Withdraw(opts *bind.TransactOpts, _recipient common.Address) (*types.Transaction, error) @@ -2418,12 +2281,6 @@ type VRFV2PlusWrapperInterface interface { ParseFulfillmentTxSizeSet(log types.Log) (*VRFV2PlusWrapperFulfillmentTxSizeSet, error) - FilterLinkNativeFeedSet(opts *bind.FilterOpts) (*VRFV2PlusWrapperLinkNativeFeedSetIterator, error) - - WatchLinkNativeFeedSet(opts *bind.WatchOpts, sink chan<- *VRFV2PlusWrapperLinkNativeFeedSet) (event.Subscription, error) - - ParseLinkNativeFeedSet(log types.Log) (*VRFV2PlusWrapperLinkNativeFeedSet, error) - FilterNativeWithdrawn(opts *bind.FilterOpts, to []common.Address) (*VRFV2PlusWrapperNativeWithdrawnIterator, error) WatchNativeWithdrawn(opts *bind.WatchOpts, sink chan<- *VRFV2PlusWrapperNativeWithdrawn, to []common.Address) (event.Subscription, 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 858ed441546..55689942cfb 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 @@ -10,11 +10,11 @@ automation_forwarder_logic: ../../contracts/solc/v0.8.16/AutomationForwarderLogi 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 20fac1208261e866caa1f3ffc71030f682a96761bebe79e5ecd71186fce86c60 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 0ec86026840302ec1db31455d039d4e2f93c2646ee48879d644fe489bf873695 +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 6ebcbbf13ec76ca685706996921eb51ee37e6ba40a35fb289c41a68922a61cc9 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 9f634b949412b06383fe53fd0531a6574e90163855238dbdd3d63589df94b77e +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 8414649696c8c602a0a12b00e98eb1d6325533870b47459d9d16ad79e6abdcf0 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 335dfe64a5cabcf12c6bac6e231919dddec5544a66cd647c229e8fe1f773ab61 +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 0de539cbc6780ae5b02956964297e41b901765f599f5fa113b0c10cf1a35bb45 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 @@ -25,16 +25,13 @@ blockhash_store: ../../contracts/solc/v0.8.19/BlockhashStore/BlockhashStore.abi chain_module_base: ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.abi ../../contracts/solc/v0.8.19/ChainModuleBase/ChainModuleBase.bin 39dfce79330e921e5c169051b11c6e5ea15cd4db5a7b09c06aabbe9658148915 chain_reader_example: ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.abi ../../contracts/solc/v0.8.19/ChainReaderTestContract/LatestValueHolder.bin de88c7e68de36b96aa2bec844bdc96fcd7c9017b38e25062b3b9f9cec42c814f chain_specific_util_helper: ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.abi ../../contracts/solc/v0.8.6/ChainSpecificUtilHelper/ChainSpecificUtilHelper.bin 5f10664e31abc768f4a37901cae7a3bef90146180f97303e5a1bde5a08d84595 -consumer_wrapper: ../../contracts/solc/v0.7/Consumer/Consumer.abi ../../contracts/solc/v0.7/Consumer/Consumer.bin 894d1cbd920dccbd36d92918c1037c6ded34f66f417ccb18ec3f33c64ef83ec5 cron_upkeep_factory_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - dacb0f8cdf54ae9d2781c5e720fc314b32ed5e58eddccff512c75d6067292cd7 cron_upkeep_wrapper: ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.abi - 362fcfcf30a6ab3acff83095ea4b2b9056dd5e9dcb94bc5411aae58995d22709 dummy_protocol_wrapper: ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.abi ../../contracts/solc/v0.8.16/DummyProtocol/DummyProtocol.bin 583a448170b13abf7ed64e406e8177d78c9e55ab44efd141eee60de23a71ee3b -flags_wrapper: ../../contracts/solc/v0.6/Flags/Flags.abi ../../contracts/solc/v0.6/Flags/Flags.bin 2034d1b562ca37a63068851915e3703980276e8d5f7db6db8a3351a49d69fc4a -flux_aggregator_wrapper: ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.bin a3b0a6396c4aa3b5ee39b3c4bd45efc89789d4859379a8a92caca3a0496c5794 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 461ef24891bd14e5ba956c2bb565715e309809d6e5cb65c39a3a932da7729915 +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 c95d3f8287af68310a29f87c9f1b760276e00a539b1a3749b968e514f4349344 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 @@ -48,8 +45,6 @@ keeper_registry_logic1_3: ../../contracts/solc/v0.8.6/KeeperRegistryLogic1_3/Kee keeper_registry_logic2_0: ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistryLogic2_0/KeeperRegistryLogic2_0.bin d69d2bc8e4844293dbc2d45abcddc50b84c88554ecccfa4fa77c0ca45ec80871 keeper_registry_logic_a_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicA2_1/KeeperRegistryLogicA2_1.bin a2327779e652a2bbd2ed2f4a7b904b696dbefd5b16e73d39be87188bde654d61 keeper_registry_logic_b_wrapper_2_1: ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.abi ../../contracts/solc/v0.8.16/KeeperRegistryLogicB2_1/KeeperRegistryLogicB2_1.bin 83b0cc20c6aa437b824f424b3e16ddcb18ab08bfa64398f143dbbf78f953dfef -keeper_registry_wrapper1_1: ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.bin 6ce079f2738f015f7374673a2816e8e9787143d00b780ea7652c8aa9ad9e1e20 -keeper_registry_wrapper1_1_mock: ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.bin 98ddb3680e86359de3b5d17e648253ba29a84703f087a1b52237824003a8c6df keeper_registry_wrapper1_2: ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/KeeperRegistry1_2.bin f6f48cc6a4e03ffc987a017041417a1db78566275ec8ed7673fbfc9052ce0215 keeper_registry_wrapper1_3: ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_3/KeeperRegistry1_3.bin d4dc760b767ae274ee25c4a604ea371e1fa603a7b6421b69efb2088ad9e8abb3 keeper_registry_wrapper2_0: ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.abi ../../contracts/solc/v0.8.6/KeeperRegistry2_0/KeeperRegistry2_0.bin c32dea7d5ef66b7c58ddc84ddf69aa44df1b3ae8601fbc271c95be4ff5853056 @@ -59,28 +54,18 @@ log_emitter: ../../contracts/solc/v0.8.19/LogEmitter/LogEmitter.abi ../../contra log_triggered_streams_lookup_wrapper: ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.abi ../../contracts/solc/v0.8.16/LogTriggeredStreamsLookup/LogTriggeredStreamsLookup.bin 920fff3b662909f12ed11b47d168036ffa74ad52070a94e2fa26cdad5e428b4e log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.abi ../../contracts/solc/v0.8.6/LogUpkeepCounter/LogUpkeepCounter.bin 42426bbb83f96dfbe55fc576d6c65020eaeed690e2289cf99b0c4aa810a5f4ec mock_aggregator_proxy: ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.abi ../../contracts/solc/v0.8.6/MockAggregatorProxy/MockAggregatorProxy.bin b16c108f3dd384c342ddff5e94da7c0a8d39d1be5e3d8f2cf61ecc7f0e50ff42 -mock_ethlink_aggregator_wrapper: ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.bin 1c52c24f797b8482aa12b8251dcea1c072827bd5b3426b822621261944b99ca0 -mock_gas_aggregator_wrapper: ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.bin bacbb1ea4dc6beac0db8a13ca5c75e2fd61b903d70feea9b3b1c8b10fe8df4f3 -multiwordconsumer_wrapper: ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.bin 6e68abdf614e3ed0f5066c1b5f9d7c1199f1e7c5c5251fe8a471344a59afc6ba offchain_aggregator_wrapper: OffchainAggregator/OffchainAggregator.abi - 5c8d6562e94166d4790f1ee6e4321d359d9f7262e6c5452a712b1f1c896f45cf operator_factory: ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin 357203fabe3df436eb015e2d5094374c6967a9fc922ac8edc265b27aac4d67cf operator_wrapper: ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin c5e1db81070d940a82ef100b0bce38e055593cbeebbc73abf9d45c30d6020cd2 optimism_module: ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.abi ../../contracts/solc/v0.8.19/OptimismModule/OptimismModule.bin a1f8ee97e12b1b2311db03b94dc52b91f3c2e9a2f8d554031a9c7b41e4432280 -oracle_wrapper: ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin 7af2fbac22a6e8c2847e8e685a5400cac5101d72ddf5365213beb79e4dede43a perform_data_checker_wrapper: ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.abi ../../contracts/solc/v0.8.16/PerformDataChecker/PerformDataChecker.bin 48d8309c2117c29a24e1155917ab0b780956b2cd6a8a39ef06ae66a7f6d94f73 scroll_module: ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.abi ../../contracts/solc/v0.8.19/ScrollModule/ScrollModule.bin 8de157cb7e5bc78146548212803d60926c8483aca7e912d802b7c66dc5d2ab11 -simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin a2532ca73e227f846be39b52fa63cfa9d088116c3cfc311d972fe8db886fa915 -solidity_vrf_consumer_interface: ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin ecc99378aa798014de9db42b2eb81320778b0663dbe208008dad75ccdc1d4366 +simple_log_upkeep_counter_wrapper: ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.abi ../../contracts/solc/v0.8.6/SimpleLogUpkeepCounter/SimpleLogUpkeepCounter.bin 7557d117a066cd8cf35f635bc085ee11795442073c18f8610ede9037b74fd814 solidity_vrf_consumer_interface_v08: ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.8.6/VRFConsumer/VRFConsumer.bin b14f9136b15e3dc9d6154d5700f3ed4cf88ddc4f70f20c3bb57fc46050904c8f -solidity_vrf_coordinator_interface: ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin a23d3c395156804788c7f6fbda2994e8f7184304c0f0c9f2c4ddeaf073d346d2 -solidity_vrf_request_id: ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin 383b59e861732c1911ddb7b002c6158608496ce889979296527215fd0366b318 solidity_vrf_request_id_v08: ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.8.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin f2559015d6f3e5d285c57b011be9b2300632e93dd6c4524e58202d6200f09edc solidity_vrf_v08_verifier_wrapper: ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.8.6/VRFTestHelper/VRFTestHelper.bin f37f8b21a81c113085c6137835a2246db6ebda07da455c4f2b5c7ec60c725c3b -solidity_vrf_verifier_wrapper: ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.bin 44c2b67d8d2990ab580453deb29d63508c6147a3dc49908a1db563bef06e6474 -solidity_vrf_wrapper: ../../contracts/solc/v0.6/VRF/VRF.abi ../../contracts/solc/v0.6/VRF/VRF.bin 04ede5b83c06ba5b76ef99c081c72928007d8a7aaefcf21449a46a07cbd4bfc2 streams_lookup_compatible_interface: ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.abi ../../contracts/solc/v0.8.16/StreamsLookupCompatibleInterface/StreamsLookupCompatibleInterface.bin 2861f553fb4731e89126b13319462df674727005a51982d1e617e2c2e44fa422 streams_lookup_upkeep_wrapper: ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.abi ../../contracts/solc/v0.8.16/StreamsLookupUpkeep/StreamsLookupUpkeep.bin 37e3a61091cc2a156539dd4aaff987e07577118aa02e97931a647df55705465e -test_api_consumer_wrapper: ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.bin ed10893cb18894c18e275302329c955f14ea2de37ee044f84aa1e067ac5ea71e trusted_blockhash_store: ../../contracts/solc/v0.8.19/TrustedBlockhashStore/TrustedBlockhashStore.abi ../../contracts/solc/v0.8.19/TrustedBlockhashStore/TrustedBlockhashStore.bin 1570663ef6feabf8660a93e85d2427ad8e7dabcfa5b418d308c62132451c5662 type_and_version_interface_wrapper: ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.abi ../../contracts/solc/v0.8.6/KeeperRegistry1_2/TypeAndVersionInterface.bin bc9c3a6e73e3ebd5b58754df0deeb3b33f4bb404d5709bb904aed51d32f4b45e upkeep_counter_wrapper: ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.8.16/UpkeepCounter/UpkeepCounter.bin cef953186d12ac802e54d17c897d01605b60bbe0ce2df3b4cf2c31c5c3168b35 @@ -126,6 +111,6 @@ vrfv2plus_client: ../../contracts/solc/v0.8.19/VRFV2PlusClient/VRFV2PlusClient.a vrfv2plus_consumer_example: ../../contracts/solc/v0.8.19/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusConsumerExample/VRFV2PlusConsumerExample.bin e25c1981638fb9ea8fdd21600d6954f999bf65b98ba4e4a3f8fb9f7858334e19 vrfv2plus_malicious_migrator: ../../contracts/solc/v0.8.19/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.abi ../../contracts/solc/v0.8.19/VRFV2PlusMaliciousMigrator/VRFV2PlusMaliciousMigrator.bin 5dff20621fe6ed3bed75fe4b65381b0d4b1f6286ee3571553dbeb57213b53416 vrfv2plus_reverting_example: ../../contracts/solc/v0.8.19/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusRevertingExample/VRFV2PlusRevertingExample.bin ebc2e96af9bf3aaa8b9cb048f8ecfec9987ee8b90126b740722c6b6427ab128e -vrfv2plus_wrapper: ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.bin a00fe9866577789d751a4ba4e198b3b07c34541b873cde404aa5a125b98b08a3 +vrfv2plus_wrapper: ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapper/VRFV2PlusWrapper.bin da748a6722ce461d27af39b4c3ebbadbd6672a9a9cd5b055ffc8c6d34df6d4f1 vrfv2plus_wrapper_consumer_example: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperConsumerExample/VRFV2PlusWrapperConsumerExample.bin 130217ffb341f19d1b3bda27f5c4a10567ac21ac3a49c9933bbdb068e8420177 vrfv2plus_wrapper_load_test_consumer: ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.abi ../../contracts/solc/v0.8.19/VRFV2PlusWrapperLoadTestConsumer/VRFV2PlusWrapperLoadTestConsumer.bin f2880b0469b82ddd4a11aa81ac12916f2912555dfe64829416a583fd82ebf3ab diff --git a/core/gethwrappers/go_generate.go b/core/gethwrappers/go_generate.go index 32539c09098..e31f7feb833 100644 --- a/core/gethwrappers/go_generate.go +++ b/core/gethwrappers/go_generate.go @@ -5,20 +5,6 @@ package gethwrappers // Make sure solidity compiler artifacts are up-to-date. Only output stdout on failure. //go:generate ./generation/compile_contracts.sh -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.abi ../../contracts/solc/v0.6/FluxAggregator/FluxAggregator.bin FluxAggregator flux_aggregator_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRF/VRF.abi ../../contracts/solc/v0.6/VRF/VRF.bin VRF solidity_vrf_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.abi ../../contracts/solc/v0.6/VRFTestHelper/VRFTestHelper.bin VRFTestHelper solidity_vrf_verifier_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.abi ../../contracts/solc/v0.6/VRFCoordinator/VRFCoordinator.bin VRFCoordinator solidity_vrf_coordinator_interface -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.abi ../../contracts/solc/v0.6/VRFConsumer/VRFConsumer.bin VRFConsumer solidity_vrf_consumer_interface -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.abi ../../contracts/solc/v0.6/VRFRequestIDBaseTestHelper/VRFRequestIDBaseTestHelper.bin VRFRequestIDBaseTestHelper solidity_vrf_request_id -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Flags/Flags.abi ../../contracts/solc/v0.6/Flags/Flags.bin Flags flags_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/Oracle/Oracle.abi ../../contracts/solc/v0.6/Oracle/Oracle.bin Oracle oracle_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.abi ../../contracts/solc/v0.6/TestAPIConsumer/TestAPIConsumer.bin TestAPIConsumer test_api_consumer_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.abi ../../contracts/solc/v0.6/MockETHLINKAggregator/MockETHLINKAggregator.bin MockETHLINKAggregator mock_ethlink_aggregator_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.abi ../../contracts/solc/v0.6/MockGASAggregator/MockGASAggregator.bin MockGASAggregator mock_gas_aggregator_wrapper - -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/Consumer/Consumer.abi ../../contracts/solc/v0.7/Consumer/Consumer.bin Consumer consumer_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.abi ../../contracts/solc/v0.7/MultiWordConsumer/MultiWordConsumer.bin MultiWordConsumer multiwordconsumer_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/Operator/Operator.abi ../../contracts/solc/v0.8.19/Operator/Operator.bin Operator operator_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.abi ../../contracts/solc/v0.8.19/OperatorFactory/OperatorFactory.bin OperatorFactory operator_factory //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.abi ../../contracts/solc/v0.8.19/AuthorizedForwarder/AuthorizedForwarder.bin AuthorizedForwarder authorized_forwarder @@ -26,10 +12,6 @@ package gethwrappers //go:generate go run ./generation/generate/wrap.go OffchainAggregator/OffchainAggregator.abi - OffchainAggregator offchain_aggregator_wrapper // Automation -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.abi ../../contracts/solc/v0.7/KeeperRegistry1_1/KeeperRegistry1_1.bin KeeperRegistry keeper_registry_wrapper1_1 -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.abi ../../contracts/solc/v0.7/KeeperRegistry1_1Mock/KeeperRegistry1_1Mock.bin KeeperRegistryMock keeper_registry_wrapper1_1_mock -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.abi ../../contracts/solc/v0.7/UpkeepPerformCounterRestrictive/UpkeepPerformCounterRestrictive.bin UpkeepPerformCounterRestrictive upkeep_perform_counter_restrictive_wrapper -//go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.7/UpkeepCounter/UpkeepCounter.abi ../../contracts/solc/v0.7/UpkeepCounter/UpkeepCounter.bin UpkeepCounter upkeep_counter_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeepFactory.abi - CronUpkeepFactory cron_upkeep_factory_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/CronUpkeepFactory/CronUpkeep.abi - CronUpkeep cron_upkeep_wrapper //go:generate go run ./generation/generate/wrap.go ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.abi ../../contracts/solc/v0.8.6/KeeperRegistrar1_2/KeeperRegistrar.bin KeeperRegistrar keeper_registrar_wrapper1_2 diff --git a/core/gethwrappers/transmission/generated/entry_point/entry_point.go b/core/gethwrappers/transmission/generated/entry_point/entry_point.go index 09a3a94a7f4..5a22214cb0e 100644 --- a/core/gethwrappers/transmission/generated/entry_point/entry_point.go +++ b/core/gethwrappers/transmission/generated/entry_point/entry_point.go @@ -79,7 +79,7 @@ type UserOperation struct { var EntryPointMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"paid\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bool\",\"name\":\"targetSuccess\",\"type\":\"bool\"},{\"internalType\":\"bytes\",\"name\":\"targetResult\",\"type\":\"bytes\"}],\"name\":\"ExecutionResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"opIndex\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"FailedOp\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderAddressResult\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureValidationFailed\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResult\",\"type\":\"error\"},{\"inputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"sigFailed\",\"type\":\"bool\"},{\"internalType\":\"uint48\",\"name\":\"validAfter\",\"type\":\"uint48\"},{\"internalType\":\"uint48\",\"name\":\"validUntil\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"paymasterContext\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.ReturnInfo\",\"name\":\"returnInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"senderInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"factoryInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"paymasterInfo\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"stake\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"internalType\":\"structIStakeManager.StakeInfo\",\"name\":\"stakeInfo\",\"type\":\"tuple\"}],\"internalType\":\"structIEntryPoint.AggregatorStakeInfo\",\"name\":\"aggregatorInfo\",\"type\":\"tuple\"}],\"name\":\"ValidationResultWithAggregation\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"}],\"name\":\"AccountDeployed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDeposit\",\"type\":\"uint256\"}],\"name\":\"Deposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"aggregator\",\"type\":\"address\"}],\"name\":\"SignatureAggregatorChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalStaked\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"unstakeDelaySec\",\"type\":\"uint256\"}],\"name\":\"StakeLocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawTime\",\"type\":\"uint256\"}],\"name\":\"StakeUnlocked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"StakeWithdrawn\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"success\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"actualGasUsed\",\"type\":\"uint256\"}],\"name\":\"UserOperationEvent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"revertReason\",\"type\":\"bytes\"}],\"name\":\"UserOperationRevertReason\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawn\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"SIG_VALIDATION_FAILED\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"}],\"name\":\"_validateSenderAndPaymaster\",\"outputs\":[],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"}],\"name\":\"addStake\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"depositTo\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"deposits\",\"outputs\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getDepositInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint112\",\"name\":\"deposit\",\"type\":\"uint112\"},{\"internalType\":\"bool\",\"name\":\"staked\",\"type\":\"bool\"},{\"internalType\":\"uint112\",\"name\":\"stake\",\"type\":\"uint112\"},{\"internalType\":\"uint32\",\"name\":\"unstakeDelaySec\",\"type\":\"uint32\"},{\"internalType\":\"uint48\",\"name\":\"withdrawTime\",\"type\":\"uint48\"}],\"internalType\":\"structIStakeManager.DepositInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"getSenderAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"getUserOpHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"userOps\",\"type\":\"tuple[]\"},{\"internalType\":\"contractIAggregator\",\"name\":\"aggregator\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structIEntryPoint.UserOpsPerAggregator[]\",\"name\":\"opsPerAggregator\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleAggregatedOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation[]\",\"name\":\"ops\",\"type\":\"tuple[]\"},{\"internalType\":\"addresspayable\",\"name\":\"beneficiary\",\"type\":\"address\"}],\"name\":\"handleOps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"paymaster\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.MemoryUserOp\",\"name\":\"mUserOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"prefund\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"contextOffset\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preOpGas\",\"type\":\"uint256\"}],\"internalType\":\"structEntryPoint.UserOpInfo\",\"name\":\"opInfo\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"}],\"name\":\"innerHandleOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"op\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"target\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"targetCallData\",\"type\":\"bytes\"}],\"name\":\"simulateHandleOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"}],\"name\":\"simulateValidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"}],\"name\":\"withdrawStake\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"addresspayable\",\"name\":\"withdrawAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"withdrawAmount\",\"type\":\"uint256\"}],\"name\":\"withdrawTo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]", - Bin: "0x60a0604052604051620000129062000050565b604051809103906000f0801580156200002f573d6000803e3d6000fd5b506001600160a01b03166080523480156200004957600080fd5b506200005e565b61020a8062004b1883390190565b608051614a97620000816000396000818161146e015261363d0152614a976000f3fe6080604052600436106101125760003560e01c8063957122ab116100a5578063bb9fe6bf11610074578063d6383f9411610059578063d6383f941461042c578063ee2194231461044c578063fc7e286d1461046c57600080fd5b8063bb9fe6bf146103f7578063c23a5cea1461040c57600080fd5b8063957122ab146103845780639b249f69146103a4578063a6193531146103c4578063b760faf9146103e457600080fd5b80634b1d7cf5116100e15780634b1d7cf5146101ad5780635287ce12146101cd57806370a082311461031c5780638f41ec5a1461036f57600080fd5b80630396cb60146101275780631d7327561461013a5780631fad948c1461016d578063205c28781461018d57600080fd5b366101225761012033610546565b005b600080fd5b6101206101353660046139b0565b6105c1565b34801561014657600080fd5b5061015a610155366004613c27565b610944565b6040519081526020015b60405180910390f35b34801561017957600080fd5b50610120610188366004613d32565b610af7565b34801561019957600080fd5b506101206101a8366004613d89565b610c38565b3480156101b957600080fd5b506101206101c8366004613d32565b610e3a565b3480156101d957600080fd5b506102bd6101e8366004613db5565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525073ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604091829020825160a08101845281546dffffffffffffffffffffffffffff80821683526e010000000000000000000000000000820460ff161515948301949094526f0100000000000000000000000000000090049092169282019290925260019091015463ffffffff81166060830152640100000000900465ffffffffffff16608082015290565b6040805182516dffffffffffffffffffffffffffff908116825260208085015115159083015283830151169181019190915260608083015163ffffffff169082015260809182015165ffffffffffff169181019190915260a001610164565b34801561032857600080fd5b5061015a610337366004613db5565b73ffffffffffffffffffffffffffffffffffffffff166000908152602081905260409020546dffffffffffffffffffffffffffff1690565b34801561037b57600080fd5b5061015a600181565b34801561039057600080fd5b5061012061039f366004613dd2565b6112d9565b3480156103b057600080fd5b506101206103bf366004613e57565b611431565b3480156103d057600080fd5b5061015a6103df366004613eb2565b611533565b6101206103f2366004613db5565b610546565b34801561040357600080fd5b50610120611575565b34801561041857600080fd5b50610120610427366004613db5565b61172c565b34801561043857600080fd5b50610120610447366004613ee7565b611a2c565b34801561045857600080fd5b50610120610467366004613eb2565b611b5a565b34801561047857600080fd5b506104f9610487366004613db5565b600060208190529081526040902080546001909101546dffffffffffffffffffffffffffff808316926e010000000000000000000000000000810460ff16926f010000000000000000000000000000009091049091169063ffffffff811690640100000000900465ffffffffffff1685565b604080516dffffffffffffffffffffffffffff96871681529415156020860152929094169183019190915263ffffffff16606082015265ffffffffffff909116608082015260a001610164565b6105508134611ec2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526020818152604091829020805492516dffffffffffffffffffffffffffff909316835292917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b33600090815260208190526040902063ffffffff8216610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c617900000000000060448201526064015b60405180910390fd5b600181015463ffffffff90811690831610156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610639565b80546000906106ed9034906f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16613f78565b905060008111610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152606401610639565b6dffffffffffffffffffffffffffff8111156107d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152606401610639565b6040805160a08101825283546dffffffffffffffffffffffffffff90811682526001602080840182815286841685870190815263ffffffff808b16606088019081526000608089018181523380835296829052908a9020985189549551945189166f01000000000000000000000000000000027fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff9515156e010000000000000000000000000000027fffffffffffffffffffffffffffffffffff0000000000000000000000000000009097169190991617949094179290921695909517865551949092018054925165ffffffffffff16640100000000027fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000909316949093169390931717905590517fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0190610937908490879091825263ffffffff16602082015260400190565b60405180910390a2505050565b6000805a90503330146109b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152606401610639565b8451604081015160608201518101611388015a10156109f6577fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b875160009015610a97576000610a13846000015160008c86611fbf565b905080610a95576000610a27610800611fd7565b805190915015610a8f57846000015173ffffffffffffffffffffffffffffffffffffffff168a602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201876020015184604051610a86929190614006565b60405180910390a35b60019250505b505b600088608001515a8603019050610ae96000838b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250612003915050565b9a9950505050505050505050565b8160008167ffffffffffffffff811115610b1357610b136139d6565b604051908082528060200260200182016040528015610b4c57816020015b610b3961390c565b815260200190600190039081610b315790505b50905060005b82811015610bc5576000828281518110610b6e57610b6e61401f565b60200260200101519050600080610ba9848a8a87818110610b9157610b9161401f565b9050602002810190610ba3919061404e565b856123e1565b91509150610bba84838360006125a3565b505050600101610b52565b506000805b83811015610c2557610c1981888884818110610be857610be861401f565b9050602002810190610bfa919061404e565b858481518110610c0c57610c0c61401f565b60200260200101516127f8565b90910190600101610bca565b50610c30848261297d565b505050505050565b33600090815260208190526040902080546dffffffffffffffffffffffffffff16821115610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610639565b8054610cdf9083906dffffffffffffffffffffffffffff1661408c565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161781556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114610dc4576040519150601f19603f3d011682016040523d82523d6000602084013e610dc9565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152606401610639565b50505050565b816000805b828110156110335736868683818110610e5a57610e5a61401f565b9050602002810190610e6c91906140a3565b9050366000610e7b83806140d7565b90925090506000610e926040850160208601613db5565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff8116156110105773ffffffffffffffffffffffffffffffffffffffff811663e3563a4f8484610f7a604089018961413f565b6040518563ffffffff1660e01b8152600401610f999493929190614355565b60006040518083038186803b158015610fb157600080fd5b505afa925050508015610fc2575060015b611010576040517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610639565b61101a8287613f78565b955050505050808061102b9061440c565b915050610e3f565b5060008167ffffffffffffffff81111561104f5761104f6139d6565b60405190808252806020026020018201604052801561108857816020015b61107561390c565b81526020019060019003908161106d5790505b5090506000805b8481101561117357368888838181106110aa576110aa61401f565b90506020028101906110bc91906140a3565b90503660006110cb83806140d7565b909250905060006110e26040850160208601613db5565b90508160005b8181101561115a5760008989815181106111045761110461401f565b602002602001015190506000806111278b898987818110610b9157610b9161401f565b91509150611137848383896125a3565b8a6111418161440c565b9b505050505080806111529061440c565b9150506110e8565b505050505050808061116b9061440c565b91505061108f565b50600080915060005b8581101561129957368989838181106111975761119761401f565b90506020028101906111a991906140a3565b90506111bb6040820160208301613db5565b73ffffffffffffffffffffffffffffffffffffffff167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a236600061120a83806140d7565b90925090508060005b8181101561128157611255888585848181106112315761123161401f565b9050602002810190611243919061404e565b8b8b81518110610c0c57610c0c61401f565b61125f9088613f78565b96508761126b8161440c565b98505080806112799061440c565b915050611213565b505050505080806112919061440c565b91505061117c565b506040516000907f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d908290a26112cf868261297d565b5050505050505050565b831580156112fc575073ffffffffffffffffffffffffffffffffffffffff83163b155b15611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006044820152606401610639565b601481106113f557600061137a6014828486614444565b6113839161446e565b60601c9050803b6000036113f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f41413330207061796d6173746572206e6f74206465706c6f79656400000000006044820152606401610639565b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260006024820152604401610639565b6040517f570e1a3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063570e1a36906114a590859085906004016144b6565b6020604051808303816000875af11580156114c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e891906144ca565b6040517f6ca7b80600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610639565b600061153e82612ac9565b6040805160208101929092523090820152466060820152608001604051602081830303815290604052805190602001209050919050565b3360009081526020819052604081206001810154909163ffffffff90911690036115fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152606401610639565b80546e010000000000000000000000000000900460ff16611678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152606401610639565b60018101546000906116909063ffffffff16426144e7565b6001830180547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff1664010000000065ffffffffffff84169081029190911790915583547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff16845560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105b5565b33600090815260208190526040902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16806117c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152606401610639565b6001820154640100000000900465ffffffffffff16611842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610639565b60018201544264010000000090910465ffffffffffff1611156118c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610639565b6001820180547fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000016905581547fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff1682556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146119bc576040519150601f19603f3d011682016040523d82523d6000602084013e6119c1565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610639565b611a3461390c565b611a3d85612ae2565b600080611a4c600088856123e1565b915091506000611a5c8383612bd5565b9050611a6743600052565b6000611a7560008a876127f8565b9050611a8043600052565b6000606073ffffffffffffffffffffffffffffffffffffffff8a1615611b10578973ffffffffffffffffffffffffffffffffffffffff168989604051611ac7929190614511565b6000604051808303816000865af19150503d8060008114611b04576040519150601f19603f3d011682016040523d82523d6000602084013e611b09565b606091505b5090925090505b8660800151838560200151866040015185856040517f8b7ac98000000000000000000000000000000000000000000000000000000000815260040161063996959493929190614521565b611b6261390c565b611b6b82612ae2565b600080611b7a600085856123e1565b845160a001516040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff958616835282825284832080546dffffffffffffffffffffffffffff6f01000000000000000000000000000000918290048116875260019283015463ffffffff9081169094528d51518851808a018a5287815280870188815291909a16875286865288872080549390930490911689529101549091169052835180850190945281845283015293955091935090366000611c4860408a018a61413f565b909250905060006014821015611c5f576000611c7a565b611c6d601460008486614444565b611c769161446e565b60601c5b6040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff861683529082905292902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1682526001015463ffffffff1690915290915093505050506000611cf88686612bd5565b90506000816000015190506000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060006040518060c001604052808b6080015181526020018b6040015181526020018315158152602001856020015165ffffffffffff168152602001856040015165ffffffffffff168152602001611d8f8c6060015190565b9052905073ffffffffffffffffffffffffffffffffffffffff831615801590611dcf575073ffffffffffffffffffffffffffffffffffffffff8316600114155b15611e885760408051808201825273ffffffffffffffffffffffffffffffffffffffff851680825282518084018452600080825260208083018281529382528181529085902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1683526001015463ffffffff169092529082015290517ffaecb4e4000000000000000000000000000000000000000000000000000000008152610639908390899089908c9086906004016145c3565b808686896040517fe0cff05f0000000000000000000000000000000000000000000000000000000081526004016106399493929190614650565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054909190611f079084906dffffffffffffffffffffffffffff16613f78565b90506dffffffffffffffffffffffffffff811115611f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152606401610639565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161790555050565b6000806000845160208601878987f195945050505050565b60603d82811115611fe55750815b604051602082018101604052818152816000602083013e9392505050565b6000805a85519091506000908161201982612cbb565b60a083015190915073ffffffffffffffffffffffffffffffffffffffff81166120455782519350612293565b80935060008851111561229357868202955060028a600281111561206b5761206b6146a7565b146121035760608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a23409916120cb908e908d908c906004016146d6565b600060405180830381600088803b1580156120e557600080fd5b5087f11580156120f9573d6000803e3d6000fd5b5050505050612293565b60608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a234099161215e908e908d908c906004016146d6565b600060405180830381600088803b15801561217857600080fd5b5087f19350505050801561218a575060015b61229357612196614736565b806308c379a00361222657506121aa614752565b806121b55750612228565b8b816040516020016121c791906147fa565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f220266b60000000000000000000000000000000000000000000000000000000082526106399291600401614006565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526012908201527f4141353020706f73744f70207265766572740000000000000000000000000000606082015260800190565b5a85038701965081870295508589604001511015612315578a6040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f414135312070726566756e642062656c6f772061637475616c476173436f7374606082015260800190565b60408901518690036123278582611ec2565b6000808c600281111561233c5761233c6146a7565b1490508460a0015173ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff168c602001517f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f8860200151858d8f6040516123c9949392919093845291151560208401526040830152606082015260800190565b60405180910390a45050505050505095945050505050565b60008060005a84519091506123f68682612ceb565b6123ff86611533565b6020860152604081015160608201516080830151171760e087013517610100870135176effffffffffffffffffffffffffffff81111561249b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606401610639565b6000806124a784612e0b565b90506124b58a8a8a84612e65565b975091506124c243600052565b60a084015160609073ffffffffffffffffffffffffffffffffffffffff16156124f7576124f28b8b8b858761317b565b975090505b60005a87039050808b60a001351015612575578b6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413430206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60408a018390528160608b015260c08b01355a8803018a608001818152505050505050505050935093915050565b6000806125af8561343e565b915091508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461265157856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413234207369676e6174757265206572726f72000000000000000000000000606082015260800190565b80156126c257856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b60006126cd8561343e565b9250905073ffffffffffffffffffffffffffffffffffffffff81161561275857866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413334207369676e6174757265206572726f72000000000000000000000000606082015260800190565b81156127ef57866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560608201527f6500000000000000000000000000000000000000000000000000000000000000608082015260a00190565b50505050505050565b6000805a9050600061280b846060015190565b905030631d732756612820606088018861413f565b87856040518563ffffffff1660e01b8152600401612841949392919061483f565b6020604051808303816000875af192505050801561289a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261289791810190614900565b60015b61297157600060206000803e506000517f2152215300000000000000000000000000000000000000000000000000000000810161293c57866040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052600f908201527f41413935206f7574206f66206761730000000000000000000000000000000000606082015260800190565b600085608001515a61294e908661408c565b6129589190613f78565b9050612968886002888685612003565b94505050612974565b92505b50509392505050565b73ffffffffffffffffffffffffffffffffffffffff82166129fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610639565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612a54576040519150601f19603f3d011682016040523d82523d6000602084013e612a59565b606091505b5050905080612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610639565b505050565b6000612ad482613491565b805190602001209050919050565b3063957122ab612af5604084018461413f565b612b026020860186613db5565b612b1061012087018761413f565b6040518663ffffffff1660e01b8152600401612b30959493929190614919565b60006040518083038186803b158015612b4857600080fd5b505afa925050508015612b59575060015b612bd257612b65614736565b806308c379a003612bc65750612b79614752565b80612b845750612bc8565b805115612bc2576000816040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639929190614006565b5050565b505b3d6000803e3d6000fd5b50565b6040805160608101825260008082526020820181905291810182905290612bfb846134d0565b90506000612c08846134d0565b825190915073ffffffffffffffffffffffffffffffffffffffff8116612c2c575080515b602080840151604080860151928501519085015191929165ffffffffffff8083169085161015612c5a578193505b8065ffffffffffff168365ffffffffffff161115612c76578092505b50506040805160608101825273ffffffffffffffffffffffffffffffffffffffff909416845265ffffffffffff92831660208501529116908201529250505092915050565b60c081015160e082015160009190808203612cd7575092915050565b612ce38248830161354e565b949350505050565b612cf86020830183613db5565b73ffffffffffffffffffffffffffffffffffffffff16815260208083013590820152608080830135604083015260a0830135606083015260c0808401359183019190915260e0808401359183019190915261010083013590820152366000612d6461012085018561413f565b90925090508015612dfe576014811015612dda576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610639565b612de8601460008385614444565b612df19161446e565b60601c60a0840152610e34565b600060a084015250505050565b60a0810151600090819073ffffffffffffffffffffffffffffffffffffffff16612e36576001612e39565b60035b60ff16905060008360800151828560600151028560400151010190508360c00151810292505050919050565b60008060005a8551805191925090612e8a8988612e8560408c018c61413f565b613566565b60a0820151612e9843600052565b600073ffffffffffffffffffffffffffffffffffffffff8216612f015773ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020546dffffffffffffffffffffffffffff16888111612efa57808903612efd565b60005b9150505b606084015160208a01516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861692633a871cdd929091612f61918f91879060040161495c565b60206040518083038160008887f193505050508015612fbb575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612fb891810190614900565b60015b61306557612fc7614736565b806308c379a003612ff85750612fdb614752565b80612fe65750612ffa565b8b816040516020016121c79190614981565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141323320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b955073ffffffffffffffffffffffffffffffffffffffff82166131685773ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902080546dffffffffffffffffffffffffffff16808a111561312c578c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b81547fffffffffffffffffffffffffffffffffffff000000000000000000000000000016908a90036dffffffffffffffffffffffffffff161790555b5a85039650505050505094509492505050565b825160608181015190916000918481116131f1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152606401610639565b60a082015173ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080548784039291906dffffffffffffffffffffffffffff16898110156132a6578c6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b8981038260000160006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff1663f465c77e858e8e602001518e6040518563ffffffff1660e01b81526004016133219392919061495c565b60006040518083038160008887f19350505050801561338057506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261337d91908101906149c6565b60015b61342a5761338c614736565b806308c379a0036133bd57506133a0614752565b806133ab57506133bf565b8d816040516020016121c79190614a52565b505b8c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141333320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b909e909d509b505050505050505050505050565b6000808260000361345457506000928392509050565b600061345f846134d0565b9050806040015165ffffffffffff164211806134865750806020015165ffffffffffff1642105b905194909350915050565b60603660006134a461014085018561413f565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60408051606081018252600080825260208201819052918101919091528160a081901c65ffffffffffff811660000361350c575065ffffffffffff5b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff909316835260d09490941c602083015265ffffffffffff16928101929092525090565b600081831061355d578161355f565b825b9392505050565b8015610e345782515173ffffffffffffffffffffffffffffffffffffffff81163b156135f757846040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b8351606001516040517f570e1a3600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163570e1a36919061367590889088906004016144b6565b60206040518083038160008887f1158015613694573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906136b991906144ca565b905073ffffffffffffffffffffffffffffffffffffffff811661374157856040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146137de57856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b8073ffffffffffffffffffffffffffffffffffffffff163b60000361386757856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b60006138766014828688614444565b61387f9161446e565b60601c90508273ffffffffffffffffffffffffffffffffffffffff1686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83896000015160a001516040516138fb92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a350505050505050565b6040518060a0016040528061398b604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b8152602001600080191681526020016000815260200160008152602001600081525090565b6000602082840312156139c257600080fd5b813563ffffffff8116811461355f57600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810181811067ffffffffffffffff82111715613a2557613a256139d6565b60405250565b610100810181811067ffffffffffffffff82111715613a2557613a256139d6565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613a9057613a906139d6565b6040525050565b600067ffffffffffffffff821115613ab157613ab16139d6565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b73ffffffffffffffffffffffffffffffffffffffff81168114612bd257600080fd5b8035613b0a81613add565b919050565b6000818303610180811215613b2357600080fd5b604051613b2f81613a05565b80925061010080831215613b4257600080fd5b6040519250613b5083613a2b565b613b5985613aff565b835260208501356020840152604085013560408401526060850135606084015260808501356080840152613b8f60a08601613aff565b60a084015260c085013560c084015260e085013560e084015282825280850135602083015250610120840135604082015261014084013560608201526101608401356080820152505092915050565b60008083601f840112613bf057600080fd5b50813567ffffffffffffffff811115613c0857600080fd5b602083019150836020828501011115613c2057600080fd5b9250929050565b6000806000806101c08587031215613c3e57600080fd5b843567ffffffffffffffff80821115613c5657600080fd5b818701915087601f830112613c6a57600080fd5b8135613c7581613a97565b604051613c828282613a4c565b8281528a6020848701011115613c9757600080fd5b82602086016020830137600060208483010152809850505050613cbd8860208901613b0f565b94506101a0870135915080821115613cd457600080fd5b50613ce187828801613bde565b95989497509550505050565b60008083601f840112613cff57600080fd5b50813567ffffffffffffffff811115613d1757600080fd5b6020830191508360208260051b8501011115613c2057600080fd5b600080600060408486031215613d4757600080fd5b833567ffffffffffffffff811115613d5e57600080fd5b613d6a86828701613ced565b9094509250506020840135613d7e81613add565b809150509250925092565b60008060408385031215613d9c57600080fd5b8235613da781613add565b946020939093013593505050565b600060208284031215613dc757600080fd5b813561355f81613add565b600080600080600060608688031215613dea57600080fd5b853567ffffffffffffffff80821115613e0257600080fd5b613e0e89838a01613bde565b909750955060208801359150613e2382613add565b90935060408701359080821115613e3957600080fd5b50613e4688828901613bde565b969995985093965092949392505050565b60008060208385031215613e6a57600080fd5b823567ffffffffffffffff811115613e8157600080fd5b613e8d85828601613bde565b90969095509350505050565b60006101608284031215613eac57600080fd5b50919050565b600060208284031215613ec457600080fd5b813567ffffffffffffffff811115613edb57600080fd5b612ce384828501613e99565b60008060008060608587031215613efd57600080fd5b843567ffffffffffffffff80821115613f1557600080fd5b613f2188838901613e99565b955060208701359150613f3382613add565b90935060408601359080821115613cd457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115613f8b57613f8b613f49565b500190565b60005b83811015613fab578181015183820152602001613f93565b83811115610e345750506000910152565b60008151808452613fd4816020860160208601613f90565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b828152604060208201526000612ce36040830184613fbc565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea183360301811261408257600080fd5b9190910192915050565b60008282101561409e5761409e613f49565b500390565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261408257600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261410c57600080fd5b83018035915067ffffffffffffffff82111561412757600080fd5b6020019150600581901b3603821315613c2057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261417457600080fd5b83018035915067ffffffffffffffff82111561418f57600080fd5b602001915036819003821315613c2057600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126141d957600080fd5b830160208101925035905067ffffffffffffffff8111156141f957600080fd5b803603821315613c2057600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061016061427d8461426385613aff565b73ffffffffffffffffffffffffffffffffffffffff169052565b6020830135602085015261429460408401846141a4565b8260408701526142a78387018284614208565b925050506142b860608401846141a4565b85830360608701526142cb838284614208565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e0850152610100808401358186015250610120614312818501856141a4565b86840383880152614324848284614208565b9350505050610140614338818501856141a4565b8684038388015261434a848284614208565b979650505050505050565b6040808252810184905260006060600586901b830181019083018783805b898110156143f5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa087860301845282357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18c36030181126143d3578283fd5b6143df868d8301614251565b9550506020938401939290920191600101614373565b50505050828103602084015261434a818587614208565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361443d5761443d613f49565b5060010190565b6000808585111561445457600080fd5b8386111561446157600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156144ae5780818660140360031b1b83161692505b505092915050565b602081526000612ce3602083018486614208565b6000602082840312156144dc57600080fd5b815161355f81613add565b600065ffffffffffff80831681851680830382111561450857614508613f49565b01949350505050565b8183823760009101908152919050565b868152856020820152600065ffffffffffff8087166040840152808616606084015250831515608083015260c060a083015261456060c0830184613fbc565b98975050505050505050565b80518252602081015160208301526040810151151560408301526000606082015165ffffffffffff8082166060860152806080850151166080860152505060a082015160c060a0850152612ce360c0850182613fbc565b60006101408083526145d78184018961456c565b9150506145f1602083018780518252602090810151910152565b845160608301526020948501516080830152835160a08301529284015160c0820152815173ffffffffffffffffffffffffffffffffffffffff1660e0820152908301518051610100830152909201516101209092019190915292915050565b60e08152600061466360e083018761456c565b905061467c602083018680518252602090810151910152565b8351606083015260208401516080830152825160a0830152602083015160c083015295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60006003851061470f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b848252606060208301526147266060830185613fbc565b9050826040830152949350505050565b600060033d111561474f5760046000803e5060005160e01c5b90565b600060443d10156147605790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff81602484011181841117156147ae57505050505090565b82850191508151818111156147c65750505050505090565b843d87010160208285010111156147e05750505050505090565b6147ef60208286010187613a4c565b509095945050505050565b7f4141353020706f73744f702072657665727465643a2000000000000000000000815260008251614832816016850160208701613f90565b9190910160160192915050565b60006101c08083526148548184018789614208565b9050845173ffffffffffffffffffffffffffffffffffffffff808251166020860152602082015160408601526040820151606086015260608201516080860152608082015160a08601528060a08301511660c08601525060c081015160e085015260e08101516101008501525060208501516101208401526040850151610140840152606085015161016084015260808501516101808401528281036101a084015261434a8185613fbc565b60006020828403121561491257600080fd5b5051919050565b60608152600061492d606083018789614208565b73ffffffffffffffffffffffffffffffffffffffff861660208401528281036040840152614560818587614208565b60608152600061496f6060830186614251565b60208301949094525060400152919050565b7f414132332072657665727465643a2000000000000000000000000000000000008152600082516149b981600f850160208701613f90565b91909101600f0192915050565b600080604083850312156149d957600080fd5b825167ffffffffffffffff8111156149f057600080fd5b8301601f81018513614a0157600080fd5b8051614a0c81613a97565b604051614a198282613a4c565b828152876020848601011115614a2e57600080fd5b614a3f836020830160208701613f90565b6020969096015195979596505050505050565b7f414133332072657665727465643a2000000000000000000000000000000000008152600082516149b981600f850160208701613f9056fea164736f6c634300080f000a608060405234801561001057600080fd5b506101ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063570e1a3614610030575b600080fd5b61004361003e3660046100f9565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60008061007c601482858761016b565b61008591610195565b60601c90506000610099846014818861016b565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525084519495509360209350849250905082850182875af190506000519350806100f057600093505b50505092915050565b6000806020838503121561010c57600080fd5b823567ffffffffffffffff8082111561012457600080fd5b818501915085601f83011261013857600080fd5b81358181111561014757600080fd5b86602082850101111561015957600080fd5b60209290920196919550909350505050565b6000808585111561017b57600080fd5b8386111561018857600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156101d55780818660140360031b1b83161692505b50509291505056fea164736f6c634300080f000a", + Bin: "0x60a0604052604051620000129062000050565b604051809103906000f0801580156200002f573d6000803e3d6000fd5b506001600160a01b03166080523480156200004957600080fd5b506200005e565b61020a8062004b0483390190565b608051614a83620000816000396000818161146e015261363e0152614a836000f3fe6080604052600436106101125760003560e01c8063957122ab116100a5578063bb9fe6bf11610074578063d6383f9411610059578063d6383f941461042c578063ee2194231461044c578063fc7e286d1461046c57600080fd5b8063bb9fe6bf146103f7578063c23a5cea1461040c57600080fd5b8063957122ab146103845780639b249f69146103a4578063a6193531146103c4578063b760faf9146103e457600080fd5b80634b1d7cf5116100e15780634b1d7cf5146101ad5780635287ce12146101cd57806370a082311461031c5780638f41ec5a1461036f57600080fd5b80630396cb60146101275780631d7327561461013a5780631fad948c1461016d578063205c28781461018d57600080fd5b366101225761012033610546565b005b600080fd5b6101206101353660046139b1565b6105c1565b34801561014657600080fd5b5061015a610155366004613c28565b610944565b6040519081526020015b60405180910390f35b34801561017957600080fd5b50610120610188366004613d33565b610af7565b34801561019957600080fd5b506101206101a8366004613d8a565b610c38565b3480156101b957600080fd5b506101206101c8366004613d33565b610e3a565b3480156101d957600080fd5b506102bd6101e8366004613db6565b6040805160a0810182526000808252602082018190529181018290526060810182905260808101919091525073ffffffffffffffffffffffffffffffffffffffff1660009081526020818152604091829020825160a08101845281546dffffffffffffffffffffffffffff80821683526e010000000000000000000000000000820460ff161515948301949094526f0100000000000000000000000000000090049092169282019290925260019091015463ffffffff81166060830152640100000000900465ffffffffffff16608082015290565b6040805182516dffffffffffffffffffffffffffff908116825260208085015115159083015283830151169181019190915260608083015163ffffffff169082015260809182015165ffffffffffff169181019190915260a001610164565b34801561032857600080fd5b5061015a610337366004613db6565b73ffffffffffffffffffffffffffffffffffffffff166000908152602081905260409020546dffffffffffffffffffffffffffff1690565b34801561037b57600080fd5b5061015a600181565b34801561039057600080fd5b5061012061039f366004613dd3565b6112d9565b3480156103b057600080fd5b506101206103bf366004613e58565b611431565b3480156103d057600080fd5b5061015a6103df366004613eb3565b611533565b6101206103f2366004613db6565b610546565b34801561040357600080fd5b50610120611575565b34801561041857600080fd5b50610120610427366004613db6565b61172c565b34801561043857600080fd5b50610120610447366004613ee8565b611a2c565b34801561045857600080fd5b50610120610467366004613eb3565b611b5a565b34801561047857600080fd5b506104f9610487366004613db6565b600060208190529081526040902080546001909101546dffffffffffffffffffffffffffff808316926e010000000000000000000000000000810460ff16926f010000000000000000000000000000009091049091169063ffffffff811690640100000000900465ffffffffffff1685565b604080516dffffffffffffffffffffffffffff96871681529415156020860152929094169183019190915263ffffffff16606082015265ffffffffffff909116608082015260a001610164565b6105508134611ec2565b73ffffffffffffffffffffffffffffffffffffffff811660008181526020818152604091829020805492516dffffffffffffffffffffffffffff909316835292917f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c491015b60405180910390a25050565b33600090815260208190526040902063ffffffff8216610642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c617900000000000060448201526064015b60405180910390fd5b600181015463ffffffff90811690831610156106ba576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152606401610639565b80546000906106ed9034906f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16613f79565b905060008111610759576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152606401610639565b6dffffffffffffffffffffffffffff8111156107d1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152606401610639565b6040805160a08101825283546dffffffffffffffffffffffffffff90811682526001602080840182815286841685870190815263ffffffff808b16606088019081526000608089018181523380835296829052908a9020985189549551945189166f01000000000000000000000000000000027fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff9515156e010000000000000000000000000000027fffffffffffffffffffffffffffffffffff0000000000000000000000000000009097169190991617949094179290921695909517865551949092018054925165ffffffffffff16640100000000027fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000909316949093169390931717905590517fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c0190610937908490879091825263ffffffff16602082015260400190565b60405180910390a2505050565b6000805a90503330146109b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152606401610639565b8451604081015160608201518101611388015a10156109f6577fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b875160009015610a97576000610a13846000015160008c86611fbf565b905080610a95576000610a27610800611fd7565b805190915015610a8f57846000015173ffffffffffffffffffffffffffffffffffffffff168a602001517f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a201876020015184604051610a86929190613ffa565b60405180910390a35b60019250505b505b600088608001515a8603019050610ae96000838b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250889250612003915050565b9a9950505050505050505050565b8160008167ffffffffffffffff811115610b1357610b136139d7565b604051908082528060200260200182016040528015610b4c57816020015b610b3961390d565b815260200190600190039081610b315790505b50905060005b82811015610bc5576000828281518110610b6e57610b6e614013565b60200260200101519050600080610ba9848a8a87818110610b9157610b91614013565b9050602002810190610ba39190614042565b856123e1565b91509150610bba84838360006125a3565b505050600101610b52565b506000805b83811015610c2557610c1981888884818110610be857610be8614013565b9050602002810190610bfa9190614042565b858481518110610c0c57610c0c614013565b60200260200101516127f8565b90910190600101610bca565b50610c30848261297d565b505050505050565b33600090815260208190526040902080546dffffffffffffffffffffffffffff16821115610cc2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152606401610639565b8054610cdf9083906dffffffffffffffffffffffffffff16614080565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161781556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810184905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168360405160006040518083038185875af1925050503d8060008114610dc4576040519150601f19603f3d011682016040523d82523d6000602084013e610dc9565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152606401610639565b50505050565b816000805b828110156110335736868683818110610e5a57610e5a614013565b9050602002810190610e6c9190614093565b9050366000610e7b83806140c7565b90925090506000610e926040850160208601613db6565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff73ffffffffffffffffffffffffffffffffffffffff821601610f33576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152606401610639565b73ffffffffffffffffffffffffffffffffffffffff8116156110105773ffffffffffffffffffffffffffffffffffffffff811663e3563a4f8484610f7a604089018961412f565b6040518563ffffffff1660e01b8152600401610f999493929190614345565b60006040518083038186803b158015610fb157600080fd5b505afa925050508015610fc2575060015b611010576040517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610639565b61101a8287613f79565b955050505050808061102b906143fc565b915050610e3f565b5060008167ffffffffffffffff81111561104f5761104f6139d7565b60405190808252806020026020018201604052801561108857816020015b61107561390d565b81526020019060019003908161106d5790505b5090506000805b8481101561117357368888838181106110aa576110aa614013565b90506020028101906110bc9190614093565b90503660006110cb83806140c7565b909250905060006110e26040850160208601613db6565b90508160005b8181101561115a57600089898151811061110457611104614013565b602002602001015190506000806111278b898987818110610b9157610b91614013565b91509150611137848383896125a3565b8a611141816143fc565b9b50505050508080611152906143fc565b9150506110e8565b505050505050808061116b906143fc565b91505061108f565b50600080915060005b85811015611299573689898381811061119757611197614013565b90506020028101906111a99190614093565b90506111bb6040820160208301613db6565b73ffffffffffffffffffffffffffffffffffffffff167f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d60405160405180910390a236600061120a83806140c7565b90925090508060005b81811015611281576112558885858481811061123157611231614013565b90506020028101906112439190614042565b8b8b81518110610c0c57610c0c614013565b61125f9088613f79565b96508761126b816143fc565b9850508080611279906143fc565b915050611213565b50505050508080611291906143fc565b91505061117c565b506040516000907f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d908290a26112cf868261297d565b5050505050505050565b831580156112fc575073ffffffffffffffffffffffffffffffffffffffff83163b155b15611363576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f41413230206163636f756e74206e6f74206465706c6f796564000000000000006044820152606401610639565b601481106113f557600061137a6014828486614434565b6113839161445e565b60601c9050803b6000036113f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f41413330207061796d6173746572206e6f74206465706c6f79656400000000006044820152606401610639565b505b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526020600482015260006024820152604401610639565b6040517f570e1a3600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169063570e1a36906114a590859085906004016144a6565b6020604051808303816000875af11580156114c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e891906144ba565b6040517f6ca7b80600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401610639565b600061153e82612ac9565b6040805160208101929092523090820152466060820152608001604051602081830303815290604052805190602001209050919050565b3360009081526020819052604081206001810154909163ffffffff90911690036115fb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152606401610639565b80546e010000000000000000000000000000900460ff16611678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152606401610639565b60018101546000906116909063ffffffff16426144d7565b6001830180547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff1664010000000065ffffffffffff84169081029190911790915583547fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff16845560405190815290915033907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a906020016105b5565b33600090815260208190526040902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff16806117c7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152606401610639565b6001820154640100000000900465ffffffffffff16611842576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152606401610639565b60018201544264010000000090910465ffffffffffff1611156118c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152606401610639565b6001820180547fffffffffffffffffffffffffffffffffffffffffffff0000000000000000000016905581547fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff1682556040805173ffffffffffffffffffffffffffffffffffffffff851681526020810183905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda3910160405180910390a260008373ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d80600081146119bc576040519150601f19603f3d011682016040523d82523d6000602084013e6119c1565b606091505b5050905080610e34576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152606401610639565b611a3461390d565b611a3d85612ae2565b600080611a4c600088856123e1565b915091506000611a5c8383612bd5565b9050611a6743600052565b6000611a7560008a876127f8565b9050611a8043600052565b6000606073ffffffffffffffffffffffffffffffffffffffff8a1615611b10578973ffffffffffffffffffffffffffffffffffffffff168989604051611ac79291906144fd565b6000604051808303816000865af19150503d8060008114611b04576040519150601f19603f3d011682016040523d82523d6000602084013e611b09565b606091505b5090925090505b8660800151838560200151866040015185856040517f8b7ac9800000000000000000000000000000000000000000000000000000000081526004016106399695949392919061450d565b611b6261390d565b611b6b82612ae2565b600080611b7a600085856123e1565b845160a001516040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff958616835282825284832080546dffffffffffffffffffffffffffff6f01000000000000000000000000000000918290048116875260019283015463ffffffff9081169094528d51518851808a018a5287815280870188815291909a16875286865288872080549390930490911689529101549091169052835180850190945281845283015293955091935090366000611c4860408a018a61412f565b909250905060006014821015611c5f576000611c7a565b611c6d601460008486614434565b611c769161445e565b60601c5b6040805180820182526000808252602080830182815273ffffffffffffffffffffffffffffffffffffffff861683529082905292902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1682526001015463ffffffff1690915290915093505050506000611cf88686612bd5565b90506000816000015190506000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614905060006040518060c001604052808b6080015181526020018b6040015181526020018315158152602001856020015165ffffffffffff168152602001856040015165ffffffffffff168152602001611d8f8c6060015190565b9052905073ffffffffffffffffffffffffffffffffffffffff831615801590611dcf575073ffffffffffffffffffffffffffffffffffffffff8316600114155b15611e885760408051808201825273ffffffffffffffffffffffffffffffffffffffff851680825282518084018452600080825260208083018281529382528181529085902080546f0100000000000000000000000000000090046dffffffffffffffffffffffffffff1683526001015463ffffffff169092529082015290517ffaecb4e4000000000000000000000000000000000000000000000000000000008152610639908390899089908c9086906004016145af565b808686896040517fe0cff05f000000000000000000000000000000000000000000000000000000008152600401610639949392919061463c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526020819052604081208054909190611f079084906dffffffffffffffffffffffffffff16613f79565b90506dffffffffffffffffffffffffffff811115611f81576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152606401610639565b81547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000166dffffffffffffffffffffffffffff919091161790555050565b6000806000845160208601878987f195945050505050565b60603d82811115611fe55750815b604051602082018101604052818152816000602083013e9392505050565b6000805a85519091506000908161201982612cbc565b60a083015190915073ffffffffffffffffffffffffffffffffffffffff81166120455782519350612293565b80935060008851111561229357868202955060028a600281111561206b5761206b614693565b146121035760608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a23409916120cb908e908d908c906004016146c2565b600060405180830381600088803b1580156120e557600080fd5b5087f11580156120f9573d6000803e3d6000fd5b5050505050612293565b60608301516040517fa9a2340900000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169163a9a234099161215e908e908d908c906004016146c2565b600060405180830381600088803b15801561217857600080fd5b5087f19350505050801561218a575060015b61229357612196614722565b806308c379a00361222657506121aa61473e565b806121b55750612228565b8b816040516020016121c791906147e6565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152908290527f220266b60000000000000000000000000000000000000000000000000000000082526106399291600401613ffa565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526012908201527f4141353020706f73744f70207265766572740000000000000000000000000000606082015260800190565b5a85038701965081870295508589604001511015612315578a6040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f414135312070726566756e642062656c6f772061637475616c476173436f7374606082015260800190565b60408901518690036123278582611ec2565b6000808c600281111561233c5761233c614693565b1490508460a0015173ffffffffffffffffffffffffffffffffffffffff16856000015173ffffffffffffffffffffffffffffffffffffffff168c602001517f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f8860200151858d8f6040516123c9949392919093845291151560208401526040830152606082015260800190565b60405180910390a45050505050505095945050505050565b60008060005a84519091506123f68682612cec565b6123ff86611533565b6020860152604081015160608201516080830151171760e087013517610100870135176effffffffffffffffffffffffffffff81111561249b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152606401610639565b6000806124a784612e0c565b90506124b58a8a8a84612e66565b975091506124c243600052565b60a084015160609073ffffffffffffffffffffffffffffffffffffffff16156124f7576124f28b8b8b858761317c565b975090505b60005a87039050808b60a001351015612575578b6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413430206f76657220766572696669636174696f6e4761734c696d69740000606082015260800190565b60408a018390528160608b015260c08b01355a8803018a608001818152505050505050505050935093915050565b6000806125af8561343f565b915091508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161461265157856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413234207369676e6174757265206572726f72000000000000000000000000606082015260800190565b80156126c257856040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f414132322065787069726564206f72206e6f7420647565000000000000000000606082015260800190565b60006126cd8561343f565b9250905073ffffffffffffffffffffffffffffffffffffffff81161561275857866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526014908201527f41413334207369676e6174757265206572726f72000000000000000000000000606082015260800190565b81156127ef57866040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526021908201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560608201527f6500000000000000000000000000000000000000000000000000000000000000608082015260a00190565b50505050505050565b6000805a9050600061280b846060015190565b905030631d732756612820606088018861412f565b87856040518563ffffffff1660e01b8152600401612841949392919061482b565b6020604051808303816000875af192505050801561289a575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612897918101906148ec565b60015b61297157600060206000803e506000517f2152215300000000000000000000000000000000000000000000000000000000810161293c57866040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052600f908201527f41413935206f7574206f66206761730000000000000000000000000000000000606082015260800190565b600085608001515a61294e9086614080565b6129589190613f79565b9050612968886002888685612003565b94505050612974565b92505b50509392505050565b73ffffffffffffffffffffffffffffffffffffffff82166129fa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152606401610639565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612a54576040519150601f19603f3d011682016040523d82523d6000602084013e612a59565b606091505b5050905080612ac4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152606401610639565b505050565b6000612ad482613492565b805190602001209050919050565b3063957122ab612af5604084018461412f565b612b026020860186613db6565b612b1061012087018761412f565b6040518663ffffffff1660e01b8152600401612b30959493929190614905565b60006040518083038186803b158015612b4857600080fd5b505afa925050508015612b59575060015b612bd257612b65614722565b806308c379a003612bc65750612b7961473e565b80612b845750612bc8565b805115612bc2576000816040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639929190613ffa565b5050565b505b3d6000803e3d6000fd5b50565b6040805160608101825260008082526020820181905291810182905290612bfb846134d1565b90506000612c08846134d1565b825190915073ffffffffffffffffffffffffffffffffffffffff8116612c2c575080515b602080840151604080860151928501519085015191929165ffffffffffff8083169085161015612c5a578193505b8065ffffffffffff168365ffffffffffff161115612c76578092505b50506040805160608101825273ffffffffffffffffffffffffffffffffffffffff909416845265ffffffffffff9283166020850152911690820152925050505b92915050565b60c081015160e082015160009190808203612cd8575092915050565b612ce48248830161354f565b949350505050565b612cf96020830183613db6565b73ffffffffffffffffffffffffffffffffffffffff16815260208083013590820152608080830135604083015260a0830135606083015260c0808401359183019190915260e0808401359183019190915261010083013590820152366000612d6561012085018561412f565b90925090508015612dff576014811015612ddb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152606401610639565b612de9601460008385614434565b612df29161445e565b60601c60a0840152610e34565b600060a084015250505050565b60a0810151600090819073ffffffffffffffffffffffffffffffffffffffff16612e37576001612e3a565b60035b60ff16905060008360800151828560600151028560400151010190508360c00151810292505050919050565b60008060005a8551805191925090612e8b8988612e8660408c018c61412f565b613567565b60a0820151612e9943600052565b600073ffffffffffffffffffffffffffffffffffffffff8216612f025773ffffffffffffffffffffffffffffffffffffffff83166000908152602081905260409020546dffffffffffffffffffffffffffff16888111612efb57808903612efe565b60005b9150505b606084015160208a01516040517f3a871cdd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff861692633a871cdd929091612f62918f918790600401614948565b60206040518083038160008887f193505050508015612fbc575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252612fb9918101906148ec565b60015b61306657612fc8614722565b806308c379a003612ff95750612fdc61473e565b80612fe75750612ffb565b8b816040516020016121c7919061496d565b505b8a6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141323320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b955073ffffffffffffffffffffffffffffffffffffffff82166131695773ffffffffffffffffffffffffffffffffffffffff8316600090815260208190526040902080546dffffffffffffffffffffffffffff16808a111561312d578c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526017908201527f41413231206469646e2774207061792070726566756e64000000000000000000606082015260800190565b81547fffffffffffffffffffffffffffffffffffff000000000000000000000000000016908a90036dffffffffffffffffffffffffffff161790555b5a85039650505050505094509492505050565b825160608181015190916000918481116131f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152606401610639565b60a082015173ffffffffffffffffffffffffffffffffffffffff8116600090815260208190526040902080548784039291906dffffffffffffffffffffffffffff16898110156132a7578c6040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601e908201527f41413331207061796d6173746572206465706f73697420746f6f206c6f770000606082015260800190565b8981038260000160006101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff1663f465c77e858e8e602001518e6040518563ffffffff1660e01b815260040161332293929190614948565b60006040518083038160008887f19350505050801561338157506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261337e91908101906149b2565b60015b61342b5761338d614722565b806308c379a0036133be57506133a161473e565b806133ac57506133c0565b8d816040516020016121c79190614a3e565b505b8c6040517f220266b60000000000000000000000000000000000000000000000000000000081526004016106399181526040602082018190526016908201527f4141333320726576657274656420286f72204f4f472900000000000000000000606082015260800190565b909e909d509b505050505050505050505050565b6000808260000361345557506000928392509050565b6000613460846134d1565b9050806040015165ffffffffffff164211806134875750806020015165ffffffffffff1642105b905194909350915050565b60603660006134a561014085018561412f565b915091508360208184030360405194506020810185016040528085528082602087013750505050919050565b60408051606081018252600080825260208201819052918101919091528160a081901c65ffffffffffff811660000361350d575065ffffffffffff5b6040805160608101825273ffffffffffffffffffffffffffffffffffffffff909316835260d09490941c602083015265ffffffffffff16928101929092525090565b600081831061355e5781613560565b825b9392505050565b8015610e345782515173ffffffffffffffffffffffffffffffffffffffff81163b156135f857846040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601f908201527f414131302073656e64657220616c726561647920636f6e737472756374656400606082015260800190565b8351606001516040517f570e1a3600000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163570e1a36919061367690889088906004016144a6565b60206040518083038160008887f1158015613695573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906136ba91906144ba565b905073ffffffffffffffffffffffffffffffffffffffff811661374257856040517f220266b6000000000000000000000000000000000000000000000000000000008152600401610639918152604060208201819052601b908201527f4141313320696e6974436f6465206661696c6564206f72204f4f470000000000606082015260800190565b8173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16146137df57856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313420696e6974436f6465206d7573742072657475726e2073656e646572606082015260800190565b8073ffffffffffffffffffffffffffffffffffffffff163b60000361386857856040517f220266b600000000000000000000000000000000000000000000000000000000815260040161063991815260406020808301829052908201527f4141313520696e6974436f6465206d757374206372656174652073656e646572606082015260800190565b60006138776014828688614434565b6138809161445e565b60601c90508273ffffffffffffffffffffffffffffffffffffffff1686602001517fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d83896000015160a001516040516138fc92919073ffffffffffffffffffffffffffffffffffffffff92831681529116602082015260400190565b60405180910390a350505050505050565b6040518060a0016040528061398c604051806101000160405280600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081526020016000815260200160008152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600081525090565b8152602001600080191681526020016000815260200160008152602001600081525090565b6000602082840312156139c357600080fd5b813563ffffffff8116811461356057600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810181811067ffffffffffffffff82111715613a2657613a266139d7565b60405250565b610100810181811067ffffffffffffffff82111715613a2657613a266139d7565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f830116810181811067ffffffffffffffff82111715613a9157613a916139d7565b6040525050565b600067ffffffffffffffff821115613ab257613ab26139d7565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b73ffffffffffffffffffffffffffffffffffffffff81168114612bd257600080fd5b8035613b0b81613ade565b919050565b6000818303610180811215613b2457600080fd5b604051613b3081613a06565b80925061010080831215613b4357600080fd5b6040519250613b5183613a2c565b613b5a85613b00565b835260208501356020840152604085013560408401526060850135606084015260808501356080840152613b9060a08601613b00565b60a084015260c085013560c084015260e085013560e084015282825280850135602083015250610120840135604082015261014084013560608201526101608401356080820152505092915050565b60008083601f840112613bf157600080fd5b50813567ffffffffffffffff811115613c0957600080fd5b602083019150836020828501011115613c2157600080fd5b9250929050565b6000806000806101c08587031215613c3f57600080fd5b843567ffffffffffffffff80821115613c5757600080fd5b818701915087601f830112613c6b57600080fd5b8135613c7681613a98565b604051613c838282613a4d565b8281528a6020848701011115613c9857600080fd5b82602086016020830137600060208483010152809850505050613cbe8860208901613b10565b94506101a0870135915080821115613cd557600080fd5b50613ce287828801613bdf565b95989497509550505050565b60008083601f840112613d0057600080fd5b50813567ffffffffffffffff811115613d1857600080fd5b6020830191508360208260051b8501011115613c2157600080fd5b600080600060408486031215613d4857600080fd5b833567ffffffffffffffff811115613d5f57600080fd5b613d6b86828701613cee565b9094509250506020840135613d7f81613ade565b809150509250925092565b60008060408385031215613d9d57600080fd5b8235613da881613ade565b946020939093013593505050565b600060208284031215613dc857600080fd5b813561356081613ade565b600080600080600060608688031215613deb57600080fd5b853567ffffffffffffffff80821115613e0357600080fd5b613e0f89838a01613bdf565b909750955060208801359150613e2482613ade565b90935060408701359080821115613e3a57600080fd5b50613e4788828901613bdf565b969995985093965092949392505050565b60008060208385031215613e6b57600080fd5b823567ffffffffffffffff811115613e8257600080fd5b613e8e85828601613bdf565b90969095509350505050565b60006101608284031215613ead57600080fd5b50919050565b600060208284031215613ec557600080fd5b813567ffffffffffffffff811115613edc57600080fd5b612ce484828501613e9a565b60008060008060608587031215613efe57600080fd5b843567ffffffffffffffff80821115613f1657600080fd5b613f2288838901613e9a565b955060208701359150613f3482613ade565b90935060408601359080821115613cd557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115612cb657612cb6613f4a565b60005b83811015613fa7578181015183820152602001613f8f565b50506000910152565b60008151808452613fc8816020860160208601613f8c565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b828152604060208201526000612ce46040830184613fb0565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600082357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea183360301811261407657600080fd5b9190910192915050565b81810381811115612cb657612cb6613f4a565b600082357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa183360301811261407657600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126140fc57600080fd5b83018035915067ffffffffffffffff82111561411757600080fd5b6020019150600581901b3603821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261416457600080fd5b83018035915067ffffffffffffffff82111561417f57600080fd5b602001915036819003821315613c2157600080fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126141c957600080fd5b830160208101925035905067ffffffffffffffff8111156141e957600080fd5b803603821315613c2157600080fd5b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600061016061426d8461425385613b00565b73ffffffffffffffffffffffffffffffffffffffff169052565b602083013560208501526142846040840184614194565b82604087015261429783870182846141f8565b925050506142a86060840184614194565b85830360608701526142bb8382846141f8565b925050506080830135608085015260a083013560a085015260c083013560c085015260e083013560e085015261010080840135818601525061012061430281850185614194565b868403838801526143148482846141f8565b935050505061014061432881850185614194565b8684038388015261433a8482846141f8565b979650505050505050565b6040808252810184905260006060600586901b830181019083018783805b898110156143e5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa087860301845282357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18c36030181126143c3578283fd5b6143cf868d8301614241565b9550506020938401939290920191600101614363565b50505050828103602084015261433a8185876141f8565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361442d5761442d613f4a565b5060010190565b6000808585111561444457600080fd5b8386111561445157600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000813581811691601485101561449e5780818660140360031b1b83161692505b505092915050565b602081526000612ce46020830184866141f8565b6000602082840312156144cc57600080fd5b815161356081613ade565b65ffffffffffff8181168382160190808211156144f6576144f6613f4a565b5092915050565b8183823760009101908152919050565b868152856020820152600065ffffffffffff8087166040840152808616606084015250831515608083015260c060a083015261454c60c0830184613fb0565b98975050505050505050565b80518252602081015160208301526040810151151560408301526000606082015165ffffffffffff8082166060860152806080850151166080860152505060a082015160c060a0850152612ce460c0850182613fb0565b60006101408083526145c381840189614558565b9150506145dd602083018780518252602090810151910152565b845160608301526020948501516080830152835160a08301529284015160c0820152815173ffffffffffffffffffffffffffffffffffffffff1660e0820152908301518051610100830152909201516101209092019190915292915050565b60e08152600061464f60e0830187614558565b9050614668602083018680518252602090810151910152565b8351606083015260208401516080830152825160a0830152602083015160c083015295945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6000600385106146fb577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b848252606060208301526147126060830185613fb0565b9050826040830152949350505050565b600060033d111561473b5760046000803e5060005160e01c5b90565b600060443d101561474c5790565b6040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc803d016004833e81513d67ffffffffffffffff816024840111818411171561479a57505050505090565b82850191508151818111156147b25750505050505090565b843d87010160208285010111156147cc5750505050505090565b6147db60208286010187613a4d565b509095945050505050565b7f4141353020706f73744f702072657665727465643a200000000000000000000081526000825161481e816016850160208701613f8c565b9190910160160192915050565b60006101c080835261484081840187896141f8565b9050845173ffffffffffffffffffffffffffffffffffffffff808251166020860152602082015160408601526040820151606086015260608201516080860152608082015160a08601528060a08301511660c08601525060c081015160e085015260e08101516101008501525060208501516101208401526040850151610140840152606085015161016084015260808501516101808401528281036101a084015261433a8185613fb0565b6000602082840312156148fe57600080fd5b5051919050565b6060815260006149196060830187896141f8565b73ffffffffffffffffffffffffffffffffffffffff86166020840152828103604084015261454c8185876141f8565b60608152600061495b6060830186614241565b60208301949094525060400152919050565b7f414132332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c565b91909101600f0192915050565b600080604083850312156149c557600080fd5b825167ffffffffffffffff8111156149dc57600080fd5b8301601f810185136149ed57600080fd5b80516149f881613a98565b604051614a058282613a4d565b828152876020848601011115614a1a57600080fd5b614a2b836020830160208701613f8c565b6020969096015195979596505050505050565b7f414133332072657665727465643a2000000000000000000000000000000000008152600082516149a581600f850160208701613f8c56fea164736f6c6343000813000a608060405234801561001057600080fd5b506101ea806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063570e1a3614610030575b600080fd5b61004361003e3660046100f9565b61006c565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b60008061007c601482858761016b565b61008591610195565b60601c90506000610099846014818861016b565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092018290525084519495509360209350849250905082850182875af190506000519350806100f057600093505b50505092915050565b6000806020838503121561010c57600080fd5b823567ffffffffffffffff8082111561012457600080fd5b818501915085601f83011261013857600080fd5b81358181111561014757600080fd5b86602082850101111561015957600080fd5b60209290920196919550909350505050565b6000808585111561017b57600080fd5b8386111561018857600080fd5b5050820193919092039150565b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000081358181169160148510156101d55780818660140360031b1b83161692505b50509291505056fea164736f6c6343000813000a", } var EntryPointABI = EntryPointMetaData.ABI diff --git a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go index 9814c6a12c0..0f9e4a7719d 100644 --- a/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go +++ b/core/gethwrappers/transmission/generated/greeter_wrapper/greeter_wrapper.go @@ -30,7 +30,7 @@ var ( var GreeterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"getGreeting\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"greeting\",\"type\":\"string\"}],\"name\":\"setGreeting\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061044a806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610050575b600080fd5b61004e61004936600461013f565b61006e565b005b61005861007e565b604051610065919061020e565b60405180910390f35b600061007a8282610323565b5050565b60606000805461008d90610281565b80601f01602080910402602001604051908101604052809291908181526020018280546100b990610281565b80156101065780601f106100db57610100808354040283529160200191610106565b820191906000526020600020905b8154815290600101906020018083116100e957829003601f168201915b5050505050905090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561015157600080fd5b813567ffffffffffffffff8082111561016957600080fd5b818401915084601f83011261017d57600080fd5b81358181111561018f5761018f610110565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d5576101d5610110565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b8181111561024d576000604083870101525b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016929092016040019392505050565b600181811c9082168061029557607f821691505b6020821081036102ce577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561031e57600081815260208120601f850160051c810160208610156102fb5750805b601f850160051c820191505b8181101561031a57828155600101610307565b5050505b505050565b815167ffffffffffffffff81111561033d5761033d610110565b6103518161034b8454610281565b846102d4565b602080601f8311600181146103a4576000841561036e5750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b17855561031a565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156103f1578886015182559484019460019091019084016103d2565b508582101561042d57878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c634300080f000a", + Bin: "0x608060405234801561001057600080fd5b50610443806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063a41368621461003b578063fe50cc7214610050575b600080fd5b61004e61004936600461013f565b61006e565b005b61005861007e565b604051610065919061020e565b60405180910390f35b600061007a828261031c565b5050565b60606000805461008d9061027a565b80601f01602080910402602001604051908101604052809291908181526020018280546100b99061027a565b80156101065780601f106100db57610100808354040283529160200191610106565b820191906000526020600020905b8154815290600101906020018083116100e957829003601f168201915b5050505050905090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60006020828403121561015157600080fd5b813567ffffffffffffffff8082111561016957600080fd5b818401915084601f83011261017d57600080fd5b81358181111561018f5761018f610110565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d5576101d5610110565b816040528281528760208487010111156101ee57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208083528351808285015260005b8181101561023b5785810183015185820160400152820161021f565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b600181811c9082168061028e57607f821691505b6020821081036102c7577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b601f82111561031757600081815260208120601f850160051c810160208610156102f45750805b601f850160051c820191505b8181101561031357828155600101610300565b5050505b505050565b815167ffffffffffffffff81111561033657610336610110565b61034a81610344845461027a565b846102cd565b602080601f83116001811461039d57600084156103675750858301515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600386901b1c1916600185901b178555610313565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b828110156103ea578886015182559484019460019091019084016103cb565b508582101561042657878501517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600388901b60f8161c191681555b5050505050600190811b0190555056fea164736f6c6343000813000a", } var GreeterABI = GreeterMetaData.ABI diff --git a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go index 4910d2b4bb9..63a2712ca3f 100644 --- a/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go +++ b/core/gethwrappers/transmission/generated/paymaster_wrapper/paymaster_wrapper.go @@ -46,7 +46,7 @@ type UserOperation struct { var PaymasterMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"linkToken\",\"type\":\"address\"},{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"linkEthFeed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"juelsNeeded\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"subscriptionBalance\",\"type\":\"uint256\"}],\"name\":\"InsufficientFunds\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidCalldata\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"OnlyCallableFromLink\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"}],\"name\":\"Unauthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"}],\"name\":\"UserOperationAlreadyTried\",\"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\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkEthFeed\",\"outputs\":[{\"internalType\":\"contractAggregatorV3Interface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_linkToken\",\"outputs\":[{\"internalType\":\"contractLinkTokenInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\":\"enumIPaymaster.PostOpMode\",\"name\":\"\",\"type\":\"uint8\"},{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"actualGasCost\",\"type\":\"uint256\"}],\"name\":\"postOp\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_config\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"stalenessSeconds\",\"type\":\"uint32\"},{\"internalType\":\"int256\",\"name\":\"fallbackWeiPerUnitLink\",\"type\":\"int256\"}],\"name\":\"setConfig\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"maxCost\",\"type\":\"uint256\"}],\"name\":\"validatePaymasterUserOp\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"context\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60e06040523480156200001157600080fd5b50604051620014fb380380620014fb8339810160408190526200003491620001a3565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000df565b5050506001600160a01b0392831660805290821660a0521660c052620001f7565b336001600160a01b03821603620001395760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001a057600080fd5b50565b600080600060608486031215620001b957600080fd5b8351620001c6816200018a565b6020850151909350620001d9816200018a565b6040850151909250620001ec816200018a565b809150509250925092565b60805160a05160c05161129c6200025f600039600081816101080152818161049f01528181610507015281816105cd015261063501526000818161018f0152610cb60152600081816101dc015281816103a201528181610ac90152610b81015261129c6000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80639b9bd4de11610081578063db37983b1161005b578063db37983b146101d7578063f2fde38b146101fe578063f465c77e1461021157600080fd5b80639b9bd4de1461018a578063a4c0ed36146101b1578063a9a23409146101c457600080fd5b806379ba5097116100b257806379ba50971461014f5780638a38f365146101595780638da5cb5b1461016c57600080fd5b8063088070f5146100ce578063140fcfb114610103575b600080fd5b6002546003546100e29163ffffffff169082565b6040805163ffffffff90931683526020830191909152015b60405180910390f35b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b610157610232565b005b610157610167366004610d5b565b610334565b60005473ffffffffffffffffffffffffffffffffffffffff1661012a565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b6101576101bf366004610dfb565b61038a565b6101576101d2366004610e57565b610487565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b61015761020c366004610eb7565b61059d565b61022461021f366004610edb565b6105b1565b6040516100fa929190610f2f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61033c610849565b6040805180820190915263ffffffff9092168083526020909201819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155600355565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103f9576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610433576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061044182840184610eb7565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054929350869290919061047b908490610fd9565b90915550505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610534576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008061054384860186610ff1565b9150915080610551846108cc565b61055b9190610fd9565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600560205260408120805490919061059090849061100f565b9091555050505050505050565b6105a5610849565b6105ae816108f8565b50565b606060003373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610662576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008481526004602052604090205460ff16156106ae576040517f7413dcf8000000000000000000000000000000000000000000000000000000008152600481018590526024016102af565b60006106b9866109ed565b90506000816106c7866108cc565b6106d19190610fd9565b905080600560006106e560208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156107b057806005600061073860208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040517f03eb8b540000000000000000000000000000000000000000000000000000000081526004016102af929190918252602082015260400190565b600086815260046020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556107f690880188610eb7565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152810183905260600160405160208183030381529060405261083b6000806000610c29565b935093505050935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102af565b565b60006108d6610c61565b6108e883670de0b6b3a7640000611026565b6108f29190611063565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff821603610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102af565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006109fd61012083018361109e565b9050601403610a0e57506000919050565b6000610a1e61012084018461109e565b6014818110610a2f57610a2f611103565b919091013560f81c9150819050610c23576000610a5061012085018561109e565b610a5e916015908290611132565b810190610a6b919061115c565b90508060200151600014158015610b385750602081015181516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201527f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3691906111e5565b105b15610c2157805160408083015190517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263a9059cbb92610bd59260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020604051808303816000875af1158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906111fe565b50806040015192505b505b50919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610c51576000610c54565b60015b60ff161717949350505050565b600254604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff1691821515918491829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163feaf968c9160048083019260a09291908290030181865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d25919061123f565b509450909250849150508015610d495750610d40824261100f565b8463ffffffff16105b15610d5357506003545b949350505050565b60008060408385031215610d6e57600080fd5b823563ffffffff81168114610d8257600080fd5b946020939093013593505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105ae57600080fd5b60008083601f840112610dc457600080fd5b50813567ffffffffffffffff811115610ddc57600080fd5b602083019150836020828501011115610df457600080fd5b9250929050565b60008060008060608587031215610e1157600080fd5b8435610e1c81610d90565b935060208501359250604085013567ffffffffffffffff811115610e3f57600080fd5b610e4b87828801610db2565b95989497509550505050565b60008060008060608587031215610e6d57600080fd5b843560038110610e7c57600080fd5b9350602085013567ffffffffffffffff811115610e9857600080fd5b610ea487828801610db2565b9598909750949560400135949350505050565b600060208284031215610ec957600080fd5b8135610ed481610d90565b9392505050565b600080600060608486031215610ef057600080fd5b833567ffffffffffffffff811115610f0757600080fd5b84016101608187031215610f1a57600080fd5b95602085013595506040909401359392505050565b604081526000835180604084015260005b81811015610f5d5760208187018101516060868401015201610f40565b81811115610f6f576000606083860101525b50602083019390935250601f919091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01601606001919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008219821115610fec57610fec610faa565b500190565b6000806040838503121561100457600080fd5b8235610d8281610d90565b60008282101561102157611021610faa565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561105e5761105e610faa565b500290565b600082611099577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126110d357600080fd5b83018035915067ffffffffffffffff8211156110ee57600080fd5b602001915036819003821315610df457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000808585111561114257600080fd5b8386111561114f57600080fd5b5050820193919092039150565b60006060828403121561116e57600080fd5b6040516060810181811067ffffffffffffffff821117156111b8577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405282356111c681610d90565b8152602083810135908201526040928301359281019290925250919050565b6000602082840312156111f757600080fd5b5051919050565b60006020828403121561121057600080fd5b81518015158114610ed457600080fd5b805169ffffffffffffffffffff8116811461123a57600080fd5b919050565b600080600080600060a0868803121561125757600080fd5b61126086611220565b945060208601519350604086015192506060860151915061128360808701611220565b9050929550929590935056fea164736f6c634300080f000a", + Bin: "0x60e06040523480156200001157600080fd5b50604051620014c4380380620014c48339810160408190526200003491620001a3565b33806000816200008b5760405162461bcd60e51b815260206004820152601860248201527f43616e6e6f7420736574206f776e657220746f207a65726f000000000000000060448201526064015b60405180910390fd5b600080546001600160a01b0319166001600160a01b0384811691909117909155811615620000be57620000be81620000df565b5050506001600160a01b0392831660805290821660a0521660c052620001f7565b336001600160a01b03821603620001395760405162461bcd60e51b815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c66000000000000000000604482015260640162000082565b600180546001600160a01b0319166001600160a01b0383811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b6001600160a01b0381168114620001a057600080fd5b50565b600080600060608486031215620001b957600080fd5b8351620001c6816200018a565b6020850151909350620001d9816200018a565b6040850151909250620001ec816200018a565b809150509250925092565b60805160a05160c0516112656200025f600039600081816101080152818161049f01528181610507015281816105cd015261063501526000818161018f0152610cb60152600081816101dc015281816103a201528181610ac90152610b8101526112656000f3fe608060405234801561001057600080fd5b50600436106100c95760003560e01c80639b9bd4de11610081578063db37983b1161005b578063db37983b146101d7578063f2fde38b146101fe578063f465c77e1461021157600080fd5b80639b9bd4de1461018a578063a4c0ed36146101b1578063a9a23409146101c457600080fd5b806379ba5097116100b257806379ba50971461014f5780638a38f365146101595780638da5cb5b1461016c57600080fd5b8063088070f5146100ce578063140fcfb114610103575b600080fd5b6002546003546100e29163ffffffff169082565b6040805163ffffffff90931683526020830191909152015b60405180910390f35b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100fa565b610157610232565b005b610157610167366004610d5b565b610334565b60005473ffffffffffffffffffffffffffffffffffffffff1661012a565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b6101576101bf366004610dfb565b61038a565b6101576101d2366004610e57565b610487565b61012a7f000000000000000000000000000000000000000000000000000000000000000081565b61015761020c366004610eb7565b61059d565b61022461021f366004610edb565b6105b1565b6040516100fa929190610f2f565b60015473ffffffffffffffffffffffffffffffffffffffff1633146102b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4d7573742062652070726f706f736564206f776e65720000000000000000000060448201526064015b60405180910390fd5b60008054337fffffffffffffffffffffffff00000000000000000000000000000000000000008083168217845560018054909116905560405173ffffffffffffffffffffffffffffffffffffffff90921692909183917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a350565b61033c610849565b6040805180820190915263ffffffff9092168083526020909201819052600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000016909217909155600355565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146103f9576040517f44b0e3c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60208114610433576040517f8129bbcd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061044182840184610eb7565b73ffffffffffffffffffffffffffffffffffffffff811660009081526005602052604081208054929350869290919061047b908490610fd1565b90915550505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610534576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008061054384860186610fe4565b9150915080610551846108cc565b61055b9190610fd1565b73ffffffffffffffffffffffffffffffffffffffff831660009081526005602052604081208054909190610590908490611002565b9091555050505050505050565b6105a5610849565b6105ae816108f8565b50565b606060003373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610662576040517f295a81c100000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001660248201526044016102af565b60008481526004602052604090205460ff16156106ae576040517f7413dcf8000000000000000000000000000000000000000000000000000000008152600481018590526024016102af565b60006106b9866109ed565b90506000816106c7866108cc565b6106d19190610fd1565b905080600560006106e560208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410156107b057806005600061073860208b018b610eb7565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546040517f03eb8b540000000000000000000000000000000000000000000000000000000081526004016102af929190918252602082015260400190565b600086815260046020908152604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556107f690880188610eb7565b6040805173ffffffffffffffffffffffffffffffffffffffff9092166020830152810183905260600160405160208183030381529060405261083b6000806000610c29565b935093505050935093915050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146108ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f4f6e6c792063616c6c61626c65206279206f776e65720000000000000000000060448201526064016102af565b565b60006108d6610c61565b6108e883670de0b6b3a7640000611015565b6108f2919061102c565b92915050565b3373ffffffffffffffffffffffffffffffffffffffff821603610977576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f43616e6e6f74207472616e7366657220746f2073656c6600000000000000000060448201526064016102af565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83811691821790925560008054604051929316917fed8889f560326eb138920d842192f0eb3dd22b4f139c87a2c57538e05bae12789190a350565b60006109fd610120830183611067565b9050601403610a0e57506000919050565b6000610a1e610120840184611067565b6014818110610a2f57610a2f6110cc565b919091013560f81c9150819050610c23576000610a50610120850185611067565b610a5e9160159082906110fb565b810190610a6b9190611125565b90508060200151600014158015610b385750602081015181516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff91821660048201527f0000000000000000000000000000000000000000000000000000000000000000909116906370a0823190602401602060405180830381865afa158015610b12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b3691906111ae565b105b15610c2157805160408083015190517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169263a9059cbb92610bd59260040173ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b6020604051808303816000875af1158015610bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c1891906111c7565b50806040015192505b505b50919050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610c51576000610c54565b60015b60ff161717949350505050565b600254604080517ffeaf968c000000000000000000000000000000000000000000000000000000008152905160009263ffffffff1691821515918491829173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169163feaf968c9160048083019260a09291908290030181865afa158015610d01573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d259190611208565b509450909250849150508015610d495750610d408242611002565b8463ffffffff16105b15610d5357506003545b949350505050565b60008060408385031215610d6e57600080fd5b823563ffffffff81168114610d8257600080fd5b946020939093013593505050565b73ffffffffffffffffffffffffffffffffffffffff811681146105ae57600080fd5b60008083601f840112610dc457600080fd5b50813567ffffffffffffffff811115610ddc57600080fd5b602083019150836020828501011115610df457600080fd5b9250929050565b60008060008060608587031215610e1157600080fd5b8435610e1c81610d90565b935060208501359250604085013567ffffffffffffffff811115610e3f57600080fd5b610e4b87828801610db2565b95989497509550505050565b60008060008060608587031215610e6d57600080fd5b843560038110610e7c57600080fd5b9350602085013567ffffffffffffffff811115610e9857600080fd5b610ea487828801610db2565b9598909750949560400135949350505050565b600060208284031215610ec957600080fd5b8135610ed481610d90565b9392505050565b600080600060608486031215610ef057600080fd5b833567ffffffffffffffff811115610f0757600080fd5b84016101608187031215610f1a57600080fd5b95602085013595506040909401359392505050565b604081526000835180604084015260005b81811015610f5d5760208187018101516060868401015201610f40565b5060006060828501015260607fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168401019150508260208301529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b808201808211156108f2576108f2610fa2565b60008060408385031215610ff757600080fd5b8235610d8281610d90565b818103818111156108f2576108f2610fa2565b80820281158282048414176108f2576108f2610fa2565b600082611062577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe184360301811261109c57600080fd5b83018035915067ffffffffffffffff8211156110b757600080fd5b602001915036819003821315610df457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000808585111561110b57600080fd5b8386111561111857600080fd5b5050820193919092039150565b60006060828403121561113757600080fd5b6040516060810181811067ffffffffffffffff82111715611181577f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604052823561118f81610d90565b8152602083810135908201526040928301359281019290925250919050565b6000602082840312156111c057600080fd5b5051919050565b6000602082840312156111d957600080fd5b81518015158114610ed457600080fd5b805169ffffffffffffffffffff8116811461120357600080fd5b919050565b600080600080600060a0868803121561122057600080fd5b611229866111e9565b945060208601519350604086015192506060860151915061124c608087016111e9565b9050929550929590935056fea164736f6c6343000813000a", } var PaymasterABI = PaymasterMetaData.ABI diff --git a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go index 55a3107710a..989e4058685 100644 --- a/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go +++ b/core/gethwrappers/transmission/generated/sca_wrapper/sca_wrapper.go @@ -44,7 +44,7 @@ type UserOperation struct { var SCAMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"BadFormatOrOOG\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentNonce\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"nonceGiven\",\"type\":\"uint256\"}],\"name\":\"IncorrectNonce\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"operationHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"NotAuthorized\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"currentTimestamp\",\"type\":\"uint256\"}],\"name\":\"TransactionExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint48\",\"name\":\"deadline\",\"type\":\"uint48\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"executeTransactionFromEntryPoint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_entryPoint\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"i_owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"s_nonce\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"nonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"callGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"verificationGasLimit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"preVerificationGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxPriorityFeePerGas\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"paymasterAndData\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"signature\",\"type\":\"bytes\"}],\"internalType\":\"structUserOperation\",\"name\":\"userOp\",\"type\":\"tuple\"},{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"validateUserOp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"validationData\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", - Bin: "0x60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526103c301526000818161010101526102ee0152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb36600461063a565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106ce565b6103ab565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006102908430604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b905060006102a261014087018761076b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061031c90508284610544565b73ffffffffffffffffffffffffffffffffffffffff161461034d576103446001600080610602565b925050506103a4565b60008054908061035c83610806565b9091555060009050610371606088018861076b565b61037f91600490829061083e565b81019061038c9190610897565b509250505061039e6000826000610602565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461041c576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061043a57508265ffffffffffff1642115b15610481576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516104ac929190610993565b60006040518083038185875af1925050503d80600081146104e9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ee565b606091505b50915091508161053b578051600003610533576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b602082015160408084015184516000939284918791908110610568576105686109a3565b016020015160f81c905060018561058083601b6109d2565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105cf573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561062a57600061062d565b60015b60ff161717949350505050565b60008060006060848603121561064f57600080fd5b833567ffffffffffffffff81111561066657600080fd5b8401610160818703121561067957600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b50565b803565ffffffffffff811681146106c957600080fd5b919050565b6000806000806000608086880312156106e657600080fd5b85356106f18161068e565b945060208601359350610706604087016106b3565b9250606086013567ffffffffffffffff8082111561072357600080fd5b818801915088601f83011261073757600080fd5b81358181111561074657600080fd5b89602082850101111561075857600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107a057600080fd5b83018035915067ffffffffffffffff8211156107bb57600080fd5b6020019150368190038213156107d057600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610837576108376107d7565b5060010190565b6000808585111561084e57600080fd5b8386111561085b57600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108ad57600080fd5b84356108b88161068e565b9350602085013592506108cd604086016106b3565b9150606085013567ffffffffffffffff808211156108ea57600080fd5b818701915087601f8301126108fe57600080fd5b81358181111561091057610910610868565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561095657610956610868565b816040528281528a602084870101111561096f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff821660ff84168060ff038211156109ef576109ef6107d7565b01939250505056fea164736f6c634300080f000a", + Bin: "0x60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000a", } var SCAABI = SCAMetaData.ABI diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go index 0b4daf3fa89..aa9205641c5 100644 --- a/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go +++ b/core/gethwrappers/transmission/generated/smart_contract_account_factory/smart_contract_account_factory.go @@ -32,7 +32,7 @@ var ( var SmartContractAccountFactoryMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[],\"name\":\"DeploymentFailed\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"ContractCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"abiEncodedOwnerAddress\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"name\":\"deploySmartContractAccount\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"stateMutability\":\"payable\",\"type\":\"function\"}]", - Bin: "0x608060405234801561001057600080fd5b5061021e806100206000396000f3fe60806040526004361061001e5760003560e01c80630af4926f14610023575b600080fd5b610036610031366004610138565b61005f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000828251836020016000f5905073ffffffffffffffffffffffffffffffffffffffff81166100ba576040517f3011642500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff821681527fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca3129060200160405180910390a192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561014b57600080fd5b82359150602083013567ffffffffffffffff8082111561016a57600080fd5b818501915085601f83011261017e57600080fd5b81358181111561019057610190610109565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d6576101d6610109565b816040528281528860208487010111156101ef57600080fd5b826020860160208301376000602084830101528095505050505050925092905056fea164736f6c634300080f000a", + Bin: "0x608060405234801561001057600080fd5b5061021e806100206000396000f3fe60806040526004361061001e5760003560e01c80630af4926f14610023575b600080fd5b610036610031366004610138565b61005f565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200160405180910390f35b6000828251836020016000f5905073ffffffffffffffffffffffffffffffffffffffff81166100ba576040517f3011642500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60405173ffffffffffffffffffffffffffffffffffffffff821681527fcf78cf0d6f3d8371e1075c69c492ab4ec5d8cf23a1a239b6a51a1d00be7ca3129060200160405180910390a192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806040838503121561014b57600080fd5b82359150602083013567ffffffffffffffff8082111561016a57600080fd5b818501915085601f83011261017e57600080fd5b81358181111561019057610190610109565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156101d6576101d6610109565b816040528281528860208487010111156101ef57600080fd5b826020860160208301376000602084830101528095505050505050925092905056fea164736f6c6343000813000a", } var SmartContractAccountFactoryABI = SmartContractAccountFactoryMetaData.ABI diff --git a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go index d951227c3a5..36e63e3683e 100644 --- a/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go +++ b/core/gethwrappers/transmission/generated/smart_contract_account_helper/smart_contract_account_helper.go @@ -30,7 +30,7 @@ var ( var SmartContractAccountHelperMetaData = &bind.MetaData{ ABI: "[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"}],\"name\":\"calculateSmartContractAccountAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"topupThreshold\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"topupAmount\",\"type\":\"uint256\"}],\"name\":\"getAbiEncodedDirectRequestData\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"endContract\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"deadline\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"getFullEndTxEncoding\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"encoding\",\"type\":\"bytes\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"userOpHash\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"scaAddress\",\"type\":\"address\"}],\"name\":\"getFullHashForSigning\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"factory\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getInitCode\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"entryPoint\",\"type\":\"address\"}],\"name\":\"getSCAInitCodeWithConstructor\",\"outputs\":[{\"internalType\":\"bytes\",\"name\":\"initCode\",\"type\":\"bytes\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}]", - Bin: "0x61162261003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061007c5760003560e01c8063e0237bef1161005a578063e0237bef14610134578063e464b3631461016c578063fc59bac31461017f57600080fd5b80632c86cb35146100815780634b770f561461010057806382311e3314610113575b600080fd5b6100ea61008f36600461076b565b604080516060808201835273ffffffffffffffffffffffffffffffffffffffff959095168082526020808301958652918301938452825191820152925183820152905182840152805180830390930183526080909101905290565b6040516100f79190610818565b60405180910390f35b6100ea61010e36600461082b565b610192565b61012661012136600461086e565b610336565b6040519081526020016100f7565b61014761014236600461082b565b610454565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f7565b6100ea61017a36600461089a565b6105df565b6100ea61018d3660046108f3565b61069d565b6040516060907fffffffffffffffffffffffffffffffffffffffff00000000000000000000000084831b16906000906101cd60208201610735565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8881166020840152871690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261026292916020016109e6565b60405160208183030381529060405290508560601b630af4926f60e01b8383604051602401610292929190610a15565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909516949094179093525161031c939201610a36565b604051602081830303815290604052925050509392505050565b600061044d8383604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b9392505050565b6040516000907fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1690829061049060208201610735565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8981166020840152881690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261052592916020016109e6565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201207fff000000000000000000000000000000000000000000000000000000000000008285015260609790971b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021840152603583019490945260558083019690965280518083039096018652607590910190525082519201919091209392505050565b6060604051806020016105f190610735565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8681166020840152851690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261068692916020016109e6565b604051602081830303815290604052905092915050565b60607f89553be40000000000000000000000000000000000000000000000000000000085856106cc8642610a7e565b856040516020016106e09493929190610abd565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261071c9291602001610b02565b6040516020818303038152906040529050949350505050565b610acb80610b4b83390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461076657600080fd5b919050565b60008060006060848603121561078057600080fd5b61078984610742565b95602085013595506040909401359392505050565b60005b838110156107b95781810151838201526020016107a1565b838111156107c8576000848401525b50505050565b600081518084526107e681602086016020860161079e565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061044d60208301846107ce565b60008060006060848603121561084057600080fd5b61084984610742565b925061085760208501610742565b915061086560408501610742565b90509250925092565b6000806040838503121561088157600080fd5b8235915061089160208401610742565b90509250929050565b600080604083850312156108ad57600080fd5b6108b683610742565b915061089160208401610742565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561090957600080fd5b61091285610742565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561093d57600080fd5b818701915087601f83011261095157600080fd5b813581811115610963576109636108c4565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f011681019083821181831017156109a9576109a96108c4565b816040528281528a60208487010111156109c257600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600083516109f881846020880161079e565b835190830190610a0c81836020880161079e565b01949350505050565b828152604060208201526000610a2e60408301846107ce565b949350505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008316815260008251610a7081601485016020870161079e565b919091016014019392505050565b60008219821115610ab8577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b500190565b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000610af860808301846107ce565b9695505050505050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251610b3c81600485016020870161079e565b91909101600401939250505056fe60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526103c301526000818161010101526102ee0152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb36600461063a565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106ce565b6103ab565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006102908430604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b905060006102a261014087018761076b565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061031c90508284610544565b73ffffffffffffffffffffffffffffffffffffffff161461034d576103446001600080610602565b925050506103a4565b60008054908061035c83610806565b9091555060009050610371606088018861076b565b61037f91600490829061083e565b81019061038c9190610897565b509250505061039e6000826000610602565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461041c576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061043a57508265ffffffffffff1642115b15610481576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516104ac929190610993565b60006040518083038185875af1925050503d80600081146104e9576040519150601f19603f3d011682016040523d82523d6000602084013e6104ee565b606091505b50915091508161053b578051600003610533576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b602082015160408084015184516000939284918791908110610568576105686109a3565b016020015160f81c905060018561058083601b6109d2565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105cf573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b8561062a57600061062d565b60015b60ff161717949350505050565b60008060006060848603121561064f57600080fd5b833567ffffffffffffffff81111561066657600080fd5b8401610160818703121561067957600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106b057600080fd5b50565b803565ffffffffffff811681146106c957600080fd5b919050565b6000806000806000608086880312156106e657600080fd5b85356106f18161068e565b945060208601359350610706604087016106b3565b9250606086013567ffffffffffffffff8082111561072357600080fd5b818801915088601f83011261073757600080fd5b81358181111561074657600080fd5b89602082850101111561075857600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107a057600080fd5b83018035915067ffffffffffffffff8211156107bb57600080fd5b6020019150368190038213156107d057600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610837576108376107d7565b5060010190565b6000808585111561084e57600080fd5b8386111561085b57600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108ad57600080fd5b84356108b88161068e565b9350602085013592506108cd604086016106b3565b9150606085013567ffffffffffffffff808211156108ea57600080fd5b818701915087601f8301126108fe57600080fd5b81358181111561091057610910610868565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561095657610956610868565b816040528281528a602084870101111561096f57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600060ff821660ff84168060ff038211156109ef576109ef6107d7565b01939250505056fea164736f6c634300080f000aa164736f6c634300080f000a", + Bin: "0x61161361003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061007c5760003560e01c8063e0237bef1161005a578063e0237bef14610134578063e464b3631461016c578063fc59bac31461017f57600080fd5b80632c86cb35146100815780634b770f561461010057806382311e3314610113575b600080fd5b6100ea61008f36600461076d565b604080516060808201835273ffffffffffffffffffffffffffffffffffffffff959095168082526020808301958652918301938452825191820152925183820152905182840152805180830390930183526080909101905290565b6040516100f7919061080e565b60405180910390f35b6100ea61010e366004610821565b610192565b610126610121366004610864565b610336565b6040519081526020016100f7565b610147610142366004610821565b610456565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f7565b6100ea61017a366004610890565b6105e1565b6100ea61018d3660046108e9565b61069f565b6040516060907fffffffffffffffffffffffffffffffffffffffff00000000000000000000000084831b16906000906101cd60208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8881166020840152871690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261026292916020016109dc565b60405160208183030381529060405290508560601b630af4926f60e01b8383604051602401610292929190610a0b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909516949094179093525161031c939201610a2c565b604051602081830303815290604052925050509392505050565b600061044d8383604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa060208083019190915281830194909452815180820383018152606080830184528151918601919091207f190000000000000000000000000000000000000000000000000000000000000060808401527f010000000000000000000000000000000000000000000000000000000000000060818401527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828401524660a284015293901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c282015260d6808201939093528151808203909301835260f6019052805191012090565b90505b92915050565b6040516000907fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606086901b1690829061049260208201610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8981166020840152881690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261052792916020016109dc565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815282825280516020918201207fff000000000000000000000000000000000000000000000000000000000000008285015260609790971b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000166021840152603583019490945260558083019690965280518083039096018652607590910190525082519201919091209392505050565b6060604051806020016105f390610737565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604081815273ffffffffffffffffffffffffffffffffffffffff8681166020840152851690820152606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261068892916020016109dc565b604051602081830303815290604052905092915050565b60607f89553be40000000000000000000000000000000000000000000000000000000085856106ce8642610a74565b856040516020016106e29493929190610aae565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529082905261071e9291602001610af3565b6040516020818303038152906040529050949350505050565b610acb80610b3c83390190565b803573ffffffffffffffffffffffffffffffffffffffff8116811461076857600080fd5b919050565b60008060006060848603121561078257600080fd5b61078b84610744565b95602085013595506040909401359392505050565b60005b838110156107bb5781810151838201526020016107a3565b50506000910152565b600081518084526107dc8160208601602086016107a0565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60208152600061044d60208301846107c4565b60008060006060848603121561083657600080fd5b61083f84610744565b925061084d60208501610744565b915061085b60408501610744565b90509250925092565b6000806040838503121561087757600080fd5b8235915061088760208401610744565b90509250929050565b600080604083850312156108a357600080fd5b6108ac83610744565b915061088760208401610744565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108ff57600080fd5b61090885610744565b93506020850135925060408501359150606085013567ffffffffffffffff8082111561093357600080fd5b818701915087601f83011261094757600080fd5b813581811115610959576109596108ba565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561099f5761099f6108ba565b816040528281528a60208487010111156109b857600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b600083516109ee8184602088016107a0565b835190830190610a028183602088016107a0565b01949350505050565b828152604060208201526000610a2460408301846107c4565b949350505050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008316815260008251610a668160148501602087016107a0565b919091016014019392505050565b80820180821115610450577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000610ae960808301846107c4565b9695505050505050565b7fffffffff000000000000000000000000000000000000000000000000000000008316815260008251610b2d8160048501602087016107a0565b91909101600401939250505056fe60c060405234801561001057600080fd5b50604051610acb380380610acb83398101604081905261002f91610062565b6001600160a01b039182166080521660a052610095565b80516001600160a01b038116811461005d57600080fd5b919050565b6000806040838503121561007557600080fd5b61007e83610046565b915061008c60208401610046565b90509250929050565b60805160a051610a046100c760003960008181607101526102b801526000818161010101526101e30152610a046000f3fe608060405234801561001057600080fd5b50600436106100675760003560e01c80637eccf63e116100505780637eccf63e146100de57806389553be4146100e7578063dba6335f146100fc57600080fd5b8063140fcfb11461006c5780633a871cdd146100bd575b600080fd5b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6100d06100cb366004610646565b610123565b6040519081526020016100b4565b6100d060005481565b6100fa6100f53660046106da565b6102a0565b005b6100937f000000000000000000000000000000000000000000000000000000000000000081565b60008054846020013514610179576000546040517f7ba633940000000000000000000000000000000000000000000000000000000081526004810191909152602085013560248201526044015b60405180910390fd5b60006101858430610439565b90506000610197610140870187610777565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016915061021190508284610550565b73ffffffffffffffffffffffffffffffffffffffff161461024257610239600160008061060e565b92505050610299565b60008054908061025183610812565b90915550600090506102666060880188610777565b61027491600490829061084a565b81019061028191906108a3565b5092505050610293600082600061060e565b93505050505b9392505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610311576040517f4a0bfec1000000000000000000000000000000000000000000000000000000008152336004820152602401610170565b65ffffffffffff83161580159061032f57508265ffffffffffff1642115b15610376576040517f300249d700000000000000000000000000000000000000000000000000000000815265ffffffffffff84166004820152426024820152604401610170565b6000808673ffffffffffffffffffffffffffffffffffffffff168685856040516103a192919061099f565b60006040518083038185875af1925050503d80600081146103de576040519150601f19603f3d011682016040523d82523d6000602084013e6103e3565b606091505b509150915081610430578051600003610428576040517f20e9b5d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b805181602001fd5b50505050505050565b604080517f4750045d47fce615521b32cee713ff8db50147e98aec5ca94926b52651ca3fa0602080830191909152818301859052825180830384018152606080840185528151918301919091207f190000000000000000000000000000000000000000000000000000000000000060808501527f010000000000000000000000000000000000000000000000000000000000000060818501527f1c7d3b72b37a35523e273aaadd7b4cd66f618bb81429ab053412d51f50ccea6160828501524660a28501529085901b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660c284015260d6808401919091528351808403909101815260f690920190925280519101205b92915050565b602082015160408084015184516000939284918791908110610574576105746109af565b016020015160f81c905060018561058c83601b6109de565b6040805160008152602081018083529390935260ff90911690820152606081018590526080810184905260a0016020604051602081039080840390855afa1580156105db573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe00151979650505050505050565b600060d08265ffffffffffff16901b60a08465ffffffffffff16901b85610636576000610639565b60015b60ff161717949350505050565b60008060006060848603121561065b57600080fd5b833567ffffffffffffffff81111561067257600080fd5b8401610160818703121561068557600080fd5b95602085013595506040909401359392505050565b73ffffffffffffffffffffffffffffffffffffffff811681146106bc57600080fd5b50565b803565ffffffffffff811681146106d557600080fd5b919050565b6000806000806000608086880312156106f257600080fd5b85356106fd8161069a565b945060208601359350610712604087016106bf565b9250606086013567ffffffffffffffff8082111561072f57600080fd5b818801915088601f83011261074357600080fd5b81358181111561075257600080fd5b89602082850101111561076457600080fd5b9699959850939650602001949392505050565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126107ac57600080fd5b83018035915067ffffffffffffffff8211156107c757600080fd5b6020019150368190038213156107dc57600080fd5b9250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203610843576108436107e3565b5060010190565b6000808585111561085a57600080fd5b8386111561086757600080fd5b5050820193919092039150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080600080608085870312156108b957600080fd5b84356108c48161069a565b9350602085013592506108d9604086016106bf565b9150606085013567ffffffffffffffff808211156108f657600080fd5b818701915087601f83011261090a57600080fd5b81358181111561091c5761091c610874565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561096257610962610874565b816040528281528a602084870101111561097b57600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60ff818116838216019081111561054a5761054a6107e356fea164736f6c6343000813000aa164736f6c6343000813000a", } var SmartContractAccountHelperABI = SmartContractAccountHelperMetaData.ABI diff --git a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt index 6d5b5c22c58..9b64d6eba0f 100644 --- a/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt +++ b/core/gethwrappers/transmission/generation/generated-wrapper-dependency-versions-do-not-edit.txt @@ -1,9 +1,9 @@ GETH_VERSION: 1.13.8 -entry_point: ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.bin 2cb4bb2ba3efa8df3dfb0a57eb3727d17b68fe202682024fa7cfb4faf026833e -greeter: ../../../contracts/solc/v0.8.15/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c -greeter_wrapper: ../../../contracts/solc/v0.8.15/Greeter/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c -paymaster_wrapper: ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.bin 189ef817a5b7a6ff53ddf35b1988465b8aec479c47b77236fe20bf7e67d48100 -sca: ../../../contracts/solc/v0.8.15/SCA.abi ../../../contracts/solc/v0.8.15/SCA.bin ae0f860cdac87d4ac505edbd228bd3ea1108550453aba67aebcb61f09cf70d0b -sca_wrapper: ../../../contracts/solc/v0.8.15/SCA/SCA.abi ../../../contracts/solc/v0.8.15/SCA/SCA.bin 2a8100fbdb41e6ce917ed333a624eaa4a8984b07e2d8d8ca6bba9bc9f74b05d7 -smart_contract_account_factory: ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.bin a44d6fa2dbf9cb3441d6d637d89e1cd656f28b6bf4146f58d508067474bf845b -smart_contract_account_helper: ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.bin 22f960a74bd1581a12aa4f8f438a3f265f32f43682f5c1897ca50707b9982d56 +entry_point: ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin e43da0e61256471b317cab1c87f2425cecba9b81ac21633334f889bab2f0777d +greeter: ../../../contracts/solc/v0.8.19/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter.bin 653dcba5c33a46292073939ce1e639372cf521c0ec2814d4c9f20c72f796f18c +greeter_wrapper: ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin 7f6def58e337a53553a46cb7992cf2d75ec951014d79376fcb869a2b16b53f6d +paymaster_wrapper: ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin dbdd1341cfa2d5c09730e0decc32339f62d1a4ea89835a51ff774226ddfbd04b +sca: ../../../contracts/solc/v0.8.19/SCA.abi ../../../contracts/solc/v0.8.19/SCA.bin ae0f860cdac87d4ac505edbd228bd3ea1108550453aba67aebcb61f09cf70d0b +sca_wrapper: ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin 6ef817bdefad1b5e84f06e0bdc40848000ab00e1a38371435b793946f425a8e6 +smart_contract_account_factory: ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin a357132e2782c462fa31ed80c270fe002e666a48ecfe407b71c278fc3a0d3679 +smart_contract_account_helper: ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin a06aff23aded74d53bd342fdc32d80c3b474ff38223df27f3395e9fd90abd12a diff --git a/core/gethwrappers/transmission/go_generate.go b/core/gethwrappers/transmission/go_generate.go index 54c6ecf94ed..b3f2b4b0eb9 100644 --- a/core/gethwrappers/transmission/go_generate.go +++ b/core/gethwrappers/transmission/go_generate.go @@ -3,9 +3,9 @@ package gethwrappers // Transmission -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Greeter/Greeter.abi ../../../contracts/solc/v0.8.15/Greeter/Greeter.bin Greeter greeter_wrapper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.15/SmartContractAccountFactory/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.15/EntryPoint/EntryPoint.bin EntryPoint entry_point -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.15/SmartContractAccountHelper/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/SCA/SCA.abi ../../../contracts/solc/v0.8.15/SCA/SCA.bin SCA sca_wrapper -//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.15/Paymaster/Paymaster.bin Paymaster paymaster_wrapper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Greeter/Greeter.abi ../../../contracts/solc/v0.8.19/Greeter/Greeter.bin Greeter greeter_wrapper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.abi ../../../contracts/solc/v0.8.19/SmartContractAccountFactory/SmartContractAccountFactory.bin SmartContractAccountFactory smart_contract_account_factory +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.abi ../../../contracts/solc/v0.8.19/EntryPoint/EntryPoint.bin EntryPoint entry_point +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.abi ../../../contracts/solc/v0.8.19/SmartContractAccountHelper/SmartContractAccountHelper.bin SmartContractAccountHelper smart_contract_account_helper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/SCA/SCA.abi ../../../contracts/solc/v0.8.19/SCA/SCA.bin SCA sca_wrapper +//go:generate go run ../generation/generate/wrap.go ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.abi ../../../contracts/solc/v0.8.19/Paymaster/Paymaster.bin Paymaster paymaster_wrapper diff --git a/core/internal/gethwrappers2/compile.sh b/core/internal/gethwrappers2/compile.sh deleted file mode 100755 index 03619da3a3e..00000000000 --- a/core/internal/gethwrappers2/compile.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash - -set -ex - -optimize_runs="$1" -solpath="$2" -solcoptions=("--optimize" "--optimize-runs" "$optimize_runs" "--metadata-hash" "none") - -basefilename="$(basename "$solpath" .sol)" -pkgname="$(echo $basefilename | tr '[:upper:]' '[:lower:]')" - -here="$(dirname $0)" -pkgdir="${here}/${pkgname}" -mkdir -p "$pkgdir" -outpath="${pkgdir}/${pkgname}.go" -abi="${pkgdir}/${basefilename}.abi" -bin="${pkgdir}/${basefilename}.bin" - -solc-select use 0.7.6 -solc --version | grep 0.7.6 || ( echo "You need solc version 0.7.6" && exit 1 ) - -# FIXME: solc seems to find and compile every .sol file in this path, so invoking this once for every file produces n*3 artifacts -solc "$solpath" ${solcoptions[@]} --abi --bin --combined-json bin,bin-runtime,srcmap-runtime --overwrite -o "$(dirname $outpath)" - -go run wrap.go "$abi" "$bin" "$basefilename" "$pkgname" diff --git a/core/internal/gethwrappers2/go_generate.go b/core/internal/gethwrappers2/go_generate.go deleted file mode 100644 index 80c3a82963a..00000000000 --- a/core/internal/gethwrappers2/go_generate.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package gethwrappers keeps track of the golang wrappers of the solidity contracts -package main - -//TODO how is OffchainAggregator generated?! https://smartcontract-it.atlassian.net/browse/BCF-1930 diff --git a/core/internal/gethwrappers2/wrap.go b/core/internal/gethwrappers2/wrap.go deleted file mode 100644 index 967e703d393..00000000000 --- a/core/internal/gethwrappers2/wrap.go +++ /dev/null @@ -1,48 +0,0 @@ -package main - -import ( - "fmt" - "os" - "path/filepath" - - gethParams "github.com/ethereum/go-ethereum/params" - - gethwrappers2 "github.com/smartcontractkit/chainlink/v2/core/gethwrappers" -) - -func main() { - abiPath := os.Args[1] - binPath := os.Args[2] - className := os.Args[3] - pkgName := os.Args[4] - fmt.Println("Generating", pkgName, "contract wrapper") - - cwd, err := os.Getwd() // gethwrappers directory - if err != nil { - gethwrappers2.Exit("could not get working directory", err) - } - outDir := filepath.Join(cwd, "generated", pkgName) - if mkdErr := os.MkdirAll(outDir, 0700); err != nil { - gethwrappers2.Exit("failed to create wrapper dir", mkdErr) - } - outPath := filepath.Join(outDir, pkgName+".go") - - gethwrappers2.Abigen(gethwrappers2.AbigenArgs{ - Bin: binPath, ABI: abiPath, Out: outPath, Type: className, Pkg: pkgName, - }) - - // Build succeeded, so update the versions db with the new contract data - versions, err := gethwrappers2.ReadVersionsDB() - if err != nil { - gethwrappers2.Exit("could not read current versions database", err) - } - versions.GethVersion = gethParams.Version - versions.ContractVersions[pkgName] = gethwrappers2.ContractVersion{ - Hash: gethwrappers2.VersionHash(abiPath, binPath), - AbiPath: abiPath, - BinaryPath: binPath, - } - if err := gethwrappers2.WriteVersionsDB(versions); err != nil { - gethwrappers2.Exit("could not save versions db", err) - } -} diff --git a/core/scripts/go.mod b/core/scripts/go.mod index ce26edc5e6d..8d45a4f908a 100644 --- a/core/scripts/go.mod +++ b/core/scripts/go.mod @@ -24,7 +24,7 @@ require ( github.com/smartcontractkit/chainlink-common v0.1.7-0.20240324144450-2bc22a6738ac github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 + github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/spf13/cobra v1.6.1 github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.9.0 @@ -52,11 +52,14 @@ require ( github.com/Depado/ginprom v1.8.0 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/NethermindEth/juno v0.3.1 // indirect + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/avast/retry-go/v4 v4.5.1 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect @@ -64,6 +67,7 @@ require ( github.com/blendle/zapdriver v1.3.1 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect github.com/btcsuite/btcd/btcutil v1.1.3 // indirect + github.com/buger/jsonparser v1.1.1 // indirect github.com/bytedance/sonic v1.10.1 // indirect github.com/cenkalti/backoff v2.2.1+incompatible // indirect github.com/cenkalti/backoff/v4 v4.2.1 // indirect @@ -150,7 +154,6 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/pprof v0.0.0-20231023181126-ff6d637d2a7b // indirect @@ -186,6 +189,7 @@ require ( github.com/huandu/skiplist v1.2.0 // indirect github.com/huin/goupnp v1.3.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect @@ -209,6 +213,7 @@ require ( github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/logrusorgru/aurora v2.0.3+incompatible // indirect github.com/magiconair/properties v1.8.7 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect @@ -250,13 +255,12 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/shirou/gopsutil/v3 v3.23.11 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // 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-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 - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect + 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 @@ -271,6 +275,7 @@ require ( github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect + github.com/test-go/testify v1.1.4 // indirect github.com/theodesp/go-heaps v0.0.0-20190520121037-88e35354fe0a // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/gjson v1.17.0 // indirect @@ -284,6 +289,7 @@ require ( github.com/ulule/limiter/v3 v3.11.2 // indirect github.com/unrolled/secure v1.13.0 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect github.com/zondax/hid v0.9.1 // indirect @@ -327,7 +333,7 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect pgregory.net/rapid v0.5.5 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( diff --git a/core/scripts/go.sum b/core/scripts/go.sum index 374a85dc75b..cef666fea63 100644 --- a/core/scripts/go.sum +++ b/core/scripts/go.sum @@ -108,6 +108,10 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0 github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -155,6 +159,8 @@ github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8P github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= 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= @@ -199,6 +205,7 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtE github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= @@ -600,8 +607,6 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -767,6 +772,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= @@ -844,6 +851,7 @@ github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= @@ -916,6 +924,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= @@ -1143,6 +1153,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1171,8 +1183,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= @@ -1187,16 +1197,16 @@ github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e h1:k8HS3GsAFZnxXIW3141VsQP2+EL1XrTtOi/HDt7sdBE= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e/go.mod h1:JiykN+8W5TA4UD2ClrzQCVvcH3NcyLEVv7RwY0busrw= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +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/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= @@ -1323,6 +1333,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1993,5 +2005,5 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/core/scripts/vrfv1/README.md b/core/scripts/vrfv1/README.md index 04d06379db3..7b8056b4b5f 100644 --- a/core/scripts/vrfv1/README.md +++ b/core/scripts/vrfv1/README.md @@ -93,7 +93,7 @@ the following steps: transferAndCall on the LinkToken contract. 2. The LinkToken contract transfers funds to the ownerless consumer. 3. The ownerless consumer requests randomness from the - [VRF Coordinator](../../../contracts/src/v0.6/VRFCoordinator.sol), using the + [VRF Coordinator](https://github.com/smartcontractkit/chainlink-contracts-deprecated/blob/main/contracts/src/v0.6/VRFCoordinator.sol), using the LINK from step 2 to pay for it. To request randomness for your chosen consumer, run: diff --git a/core/services/chainlink/config_test.go b/core/services/chainlink/config_test.go index b01a8da50d2..27e5c9317fa 100644 --- a/core/services/chainlink/config_test.go +++ b/core/services/chainlink/config_test.go @@ -186,8 +186,9 @@ var ( Chain: stkcfg.Chain{ ConfirmationPoll: commoncfg.MustNewDuration(time.Hour), }, + FeederURL: commoncfg.MustParseURL("http://feeder.url"), Nodes: []*stkcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node")}, + {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node"), APIKey: ptr("key")}, }, }, }, @@ -575,12 +576,13 @@ func TestConfig_Marshal(t *testing.T) { }, NodePool: evmcfg.NodePool{ - PollFailureThreshold: ptr[uint32](5), - PollInterval: &minute, - SelectionMode: &selectionMode, - SyncThreshold: ptr[uint32](13), - LeaseDuration: &zeroSeconds, - NodeIsSyncingEnabled: ptr(true), + PollFailureThreshold: ptr[uint32](5), + PollInterval: &minute, + SelectionMode: &selectionMode, + SyncThreshold: ptr[uint32](13), + LeaseDuration: &zeroSeconds, + NodeIsSyncingEnabled: ptr(true), + FinalizedBlockPollInterval: &second, }, OCR: evmcfg.OCR{ ContractConfirmations: ptr[uint16](11), @@ -653,8 +655,9 @@ func TestConfig_Marshal(t *testing.T) { TxTimeout: commoncfg.MustNewDuration(13 * time.Second), ConfirmationPoll: commoncfg.MustNewDuration(42 * time.Second), }, + FeederURL: commoncfg.MustParseURL("http://feeder.url"), Nodes: []*stkcfg.Node{ - {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node")}, + {Name: ptr("primary"), URL: commoncfg.MustParseURL("http://stark.node"), APIKey: ptr("key")}, }, }, } @@ -1020,6 +1023,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = true +FinalizedBlockPollInterval = '1s' [EVM.OCR] ContractConfirmations = 11 @@ -1108,6 +1112,7 @@ URL = 'http://solana.bar' `}, {"Starknet", Config{Starknet: full.Starknet}, `[[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' Enabled = true OCR2CachePollPeriod = '6h0m0s' OCR2CacheTTL = '3m0s' @@ -1118,6 +1123,7 @@ ConfirmationPoll = '42s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' `}, {"Mercury", Config{Core: toml.Core{Mercury: full.Mercury}}, `[Mercury] [Mercury.Cache] @@ -1140,6 +1146,7 @@ CertFile = '/path/to/cert.pem' require.NoError(t, config.DecodeTOML(strings.NewReader(s), &got)) ts, err := got.TOMLString() + require.NoError(t, err) assert.Equal(t, tt.config, got, diff.Diff(s, ts)) }) @@ -1545,6 +1552,7 @@ func TestConfig_SetFrom(t *testing.T) { require.NoError(t, c.SetFrom(&f)) } ts, err := c.TOMLString() + require.NoError(t, err) assert.Equal(t, tt.exp, ts) }) diff --git a/core/services/chainlink/relayer_chain_interoperators_test.go b/core/services/chainlink/relayer_chain_interoperators_test.go index 4cb6f57f8ba..c90811de768 100644 --- a/core/services/chainlink/relayer_chain_interoperators_test.go +++ b/core/services/chainlink/relayer_chain_interoperators_test.go @@ -100,32 +100,38 @@ func TestCoreRelayerChainInteroperators(t *testing.T) { c.Starknet = stkcfg.TOMLConfigs{ &stkcfg.TOMLConfig{ - ChainID: &starknetChainID1, - Enabled: ptr(true), - Chain: stkcfg.Chain{}, + ChainID: &starknetChainID1, + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + FeederURL: commonconfig.MustParseURL("http://feeder.url"), Nodes: []*stkcfg.Node{ { - Name: ptr("starknet chain 1 node 1"), - URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8547").URL())), + Name: ptr("starknet chain 1 node 1"), + URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8547").URL())), + APIKey: ptr("key"), }, { - Name: ptr("starknet chain 1 node 2"), - URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8548").URL())), + Name: ptr("starknet chain 1 node 2"), + URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8548").URL())), + APIKey: ptr("key"), }, { - Name: ptr("starknet chain 1 node 3"), - URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8549").URL())), + Name: ptr("starknet chain 1 node 3"), + URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:8549").URL())), + APIKey: ptr("key"), }, }, }, &stkcfg.TOMLConfig{ - ChainID: &starknetChainID2, - Enabled: ptr(true), - Chain: stkcfg.Chain{}, + ChainID: &starknetChainID2, + Enabled: ptr(true), + Chain: stkcfg.Chain{}, + FeederURL: commonconfig.MustParseURL("http://feeder.url"), Nodes: []*stkcfg.Node{ { - Name: ptr("starknet chain 2 node 1"), - URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:3547").URL())), + Name: ptr("starknet chain 2 node 1"), + URL: ((*commonconfig.URL)(commonconfig.MustParseURL("http://localhost:3547").URL())), + APIKey: ptr("key"), }, }, }, diff --git a/core/services/chainlink/testdata/config-full.toml b/core/services/chainlink/testdata/config-full.toml index 736c746b138..76c4aa0cade 100644 --- a/core/services/chainlink/testdata/config-full.toml +++ b/core/services/chainlink/testdata/config-full.toml @@ -342,6 +342,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = true +FinalizedBlockPollInterval = '1s' [EVM.OCR] ContractConfirmations = 11 @@ -430,6 +431,7 @@ URL = 'http://solana.bar' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' Enabled = true OCR2CachePollPeriod = '6h0m0s' OCR2CacheTTL = '3m0s' @@ -440,3 +442,4 @@ ConfirmationPoll = '42s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/core/services/chainlink/testdata/config-invalid.toml b/core/services/chainlink/testdata/config-invalid.toml index d11cd48d6ef..7d1ed17c3c2 100644 --- a/core/services/chainlink/testdata/config-invalid.toml +++ b/core/services/chainlink/testdata/config-invalid.toml @@ -132,10 +132,12 @@ Name = 'bar' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' [[Starknet.Nodes]] Name = 'primary' URL = 'http://second.stark.node' +APIKey = 'key' [[Starknet]] diff --git a/core/services/chainlink/testdata/config-multi-chain-effective.toml b/core/services/chainlink/testdata/config-multi-chain-effective.toml index 7e4e6e44d2e..67cd1770d97 100644 --- a/core/services/chainlink/testdata/config-multi-chain-effective.toml +++ b/core/services/chainlink/testdata/config-multi-chain-effective.toml @@ -313,6 +313,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -403,6 +404,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -487,6 +489,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -586,6 +589,7 @@ URL = 'http://testnet.solana.com' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' OCR2CachePollPeriod = '5s' OCR2CacheTTL = '1m0s' RequestTimeout = '10s' @@ -595,3 +599,4 @@ ConfirmationPoll = '1h0m0s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/core/services/chainlink/testdata/config-multi-chain.toml b/core/services/chainlink/testdata/config-multi-chain.toml index 53425dd1afe..e45255a4373 100644 --- a/core/services/chainlink/testdata/config-multi-chain.toml +++ b/core/services/chainlink/testdata/config-multi-chain.toml @@ -103,8 +103,10 @@ URL = 'http://testnet.solana.com' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' ConfirmationPoll = '1h0m0s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/core/services/keystore/keys/starkkey/key.go b/core/services/keystore/keys/starkkey/key.go index 62d9e077073..7723d4ce4fb 100644 --- a/core/services/keystore/keys/starkkey/key.go +++ b/core/services/keystore/keys/starkkey/key.go @@ -6,8 +6,8 @@ import ( "io" "math/big" - "github.com/smartcontractkit/caigo" - caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/NethermindEth/juno/core/felt" + "github.com/NethermindEth/starknet.go/curve" ) // Raw represents the Stark private key @@ -19,7 +19,7 @@ func (raw Raw) Key() Key { var err error k.priv = new(big.Int).SetBytes(raw) - k.pub.X, k.pub.Y, err = caigo.Curve.PrivateToPoint(k.priv) + k.pub.X, k.pub.Y, err = curve.Curve.PrivateToPoint(k.priv) if err != nil { panic(err) // key not generated } @@ -75,7 +75,7 @@ func (key Key) ID() string { // it is the X component of the ECDSA pubkey and used in the deployment of the account contract // this func is used in exporting it via CLI and API func (key Key) StarkKeyStr() string { - return caigotypes.BigToFelt(key.pub.X).String() + return new(felt.Felt).SetBytes(key.pub.X.Bytes()).String() } // Raw from private key diff --git a/core/services/keystore/keys/starkkey/ocr2key.go b/core/services/keystore/keys/starkkey/ocr2key.go index 417687b62a6..41e0db7de8e 100644 --- a/core/services/keystore/keys/starkkey/ocr2key.go +++ b/core/services/keystore/keys/starkkey/ocr2key.go @@ -7,8 +7,8 @@ import ( "github.com/pkg/errors" - "github.com/smartcontractkit/caigo" - caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/NethermindEth/juno/core/felt" + "github.com/NethermindEth/starknet.go/curve" "github.com/smartcontractkit/libocr/offchainreporting2plus/chains/evmutil" "github.com/smartcontractkit/libocr/offchainreporting2plus/types" ) @@ -26,7 +26,8 @@ func NewOCR2Key(material io.Reader) (*OCR2Key, error) { } func (sk *OCR2Key) PublicKey() types.OnchainPublicKey { - return caigotypes.BigToFelt(sk.pub.X).Bytes() + ans := new(felt.Felt).SetBytes(sk.pub.X.Bytes()).Bytes() + return ans[:] } func ReportToSigData(reportCtx types.ReportContext, report types.Report) (*big.Int, error) { @@ -46,7 +47,7 @@ func ReportToSigData(reportCtx types.ReportContext, report types.Report) (*big.I dataArray = append(dataArray, new(big.Int).SetBytes(splitReport[i])) } - hash, err := caigo.Curve.ComputeHashOnElements(dataArray) + hash, err := curve.Curve.ComputeHashOnElements(dataArray) if err != nil { return &big.Int{}, err } @@ -58,14 +59,14 @@ func (sk *OCR2Key) Sign(reportCtx types.ReportContext, report types.Report) ([]b if err != nil { return []byte{}, err } - r, s, err := caigo.Curve.Sign(hash, sk.priv) + r, s, err := curve.Curve.Sign(hash, sk.priv) if err != nil { return []byte{}, err } // enforce s <= N/2 to prevent signature malleability - if s.Cmp(new(big.Int).Rsh(caigo.Curve.N, 1)) > 0 { - s.Sub(caigo.Curve.N, s) + if s.Cmp(new(big.Int).Rsh(curve.Curve.N, 1)) > 0 { + s.Sub(curve.Curve.N, s) } // encoding: public key (32 bytes) + r (32 bytes) + s (32 bytes) @@ -97,7 +98,7 @@ func (sk *OCR2Key) Verify(publicKey types.OnchainPublicKey, reportCtx types.Repo // convert OnchainPublicKey (starkkey) into ecdsa public keys (prepend 2 or 3 to indicate +/- Y coord) var keys [2]PublicKey keys[0].X = new(big.Int).SetBytes(publicKey) - keys[0].Y = caigo.Curve.GetYCoordinate(keys[0].X) + keys[0].Y = curve.Curve.GetYCoordinate(keys[0].X) // When there is no point with the provided x-coordinate, the GetYCoordinate function returns the nil value. if keys[0].Y == nil { @@ -116,11 +117,11 @@ func (sk *OCR2Key) Verify(publicKey types.OnchainPublicKey, reportCtx types.Repo s := new(big.Int).SetBytes(signature[64:]) // Only allow canonical signatures to avoid signature malleability. Verify s <= N/2 - if s.Cmp(new(big.Int).Rsh(caigo.Curve.N, 1)) == 1 { + if s.Cmp(new(big.Int).Rsh(curve.Curve.N, 1)) == 1 { return false } - return caigo.Curve.Verify(hash, r, s, keys[0].X, keys[0].Y) || caigo.Curve.Verify(hash, r, s, keys[1].X, keys[1].Y) + return curve.Curve.Verify(hash, r, s, keys[0].X, keys[0].Y) || curve.Curve.Verify(hash, r, s, keys[1].X, keys[1].Y) } func (sk *OCR2Key) Verify3(publicKey types.OnchainPublicKey, cd types.ConfigDigest, seqNr uint64, r types.Report, signature []byte) bool { diff --git a/core/services/keystore/keys/starkkey/ocr2key_test.go b/core/services/keystore/keys/starkkey/ocr2key_test.go index e2d20258463..69436e5ce7f 100644 --- a/core/services/keystore/keys/starkkey/ocr2key_test.go +++ b/core/services/keystore/keys/starkkey/ocr2key_test.go @@ -6,7 +6,7 @@ import ( "math/big" "testing" - caigotypes "github.com/smartcontractkit/caigo/types" + "github.com/NethermindEth/juno/core/felt" ocrtypes "github.com/smartcontractkit/libocr/offchainreporting2plus/types" "github.com/stretchr/testify/assert" @@ -34,13 +34,15 @@ import ( func TestStarknetKeyring_TestVector(t *testing.T) { var kr1 OCR2Key bigKey, _ := new(big.Int).SetString("2137244795266879235401249500471353867704187908407744160927664772020405449078", 10) - feltKey := caigotypes.BigToFelt(bigKey) - err := kr1.Unmarshal(feltKey.Bytes()) + feltKey, err := new(felt.Felt).SetString(bigKey.String()) + require.NoError(t, err) + bytesKey := feltKey.Bytes() + err = kr1.Unmarshal(bytesKey[:]) require.NoError(t, err) // kr2, err := NewOCR2Key(cryptorand.Reader) // require.NoError(t, err) - bytes, err := caigotypes.HexToBytes("0x004acf99cb25a4803916f086440c661295b105a485efdc649ac4de9536da25b") + bytes, err := hex.DecodeString("0004acf99cb25a4803916f086440c661295b105a485efdc649ac4de9536da25b") require.NoError(t, err) configDigest, err := ocrtypes.BytesToConfigDigest(bytes) require.NoError(t, err) @@ -58,44 +60,51 @@ func TestStarknetKeyring_TestVector(t *testing.T) { } var report []byte - report = append(report, caigotypes.BigToFelt(big.NewInt(1)).Bytes()...) - report = append(report, caigotypes.StrToFelt("0x00010203000000000000000000000000000000000000000000000000000000").Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(4)).Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(99)).Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(99)).Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(99)).Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(99)).Bytes()...) - report = append(report, caigotypes.BigToFelt(big.NewInt(1)).Bytes()...) + b1 := new(felt.Felt).SetUint64(1).Bytes() + report = append(report, b1[:]...) + b2Bytes, err := hex.DecodeString("00010203000000000000000000000000000000000000000000000000000000") + require.NoError(t, err) + b2 := new(felt.Felt).SetBytes(b2Bytes).Bytes() + report = append(report, b2[:]...) + b3 := new(felt.Felt).SetUint64(4).Bytes() + report = append(report, b3[:]...) + b4 := new(felt.Felt).SetUint64(99).Bytes() + report = append(report, b4[:]...) + report = append(report, b4[:]...) + report = append(report, b4[:]...) + report = append(report, b4[:]...) + report = append(report, b1[:]...) // check that report hash matches expected msg, err := ReportToSigData(ctx, report) require.NoError(t, err) - expected, err := caigotypes.HexToBytes("0x1332a8dabaabef63b03438ca50760cb9f5c0292cbf015b2395e50e6157df4e3") + expected, err := new(felt.Felt).SetString("0x1332a8dabaabef63b03438ca50760cb9f5c0292cbf015b2395e50e6157df4e3") + expectedBytes := expected.Bytes() require.NoError(t, err) - assert.Equal(t, expected, msg.Bytes()) + assert.Equal(t, expectedBytes[:], msg.Bytes()) // check that signature matches expected sig, err := kr1.Sign(ctx, report) require.NoError(t, err) - pub := caigotypes.BytesToFelt(sig[0:32]) - r := caigotypes.BytesToFelt(sig[32:64]) - s := caigotypes.BytesToFelt(sig[64:]) + pub := new(felt.Felt).SetBytes(sig[0:32]) + r := new(felt.Felt).SetBytes(sig[32:64]) + s := new(felt.Felt).SetBytes(sig[64:]) bigPubExpected, _ := new(big.Int).SetString("1118148281956858477519852250235501663092798578871088714409528077622994994907", 10) - feltPubExpected := caigotypes.BigToFelt(bigPubExpected) + feltPubExpected := new(felt.Felt).SetBytes(bigPubExpected.Bytes()) assert.Equal(t, feltPubExpected, pub) bigRExpected, _ := new(big.Int).SetString("2898571078985034687500959842265381508927681132188252715370774777831313601543", 10) - feltRExpected := caigotypes.BigToFelt(bigRExpected) + feltRExpected := new(felt.Felt).SetBytes(bigRExpected.Bytes()) assert.Equal(t, feltRExpected, r) // test for malleability otherS, _ := new(big.Int).SetString("1930849708769648077928186998643944706551011476358007177069185543644456022504", 10) bigSExpected, _ := new(big.Int).SetString("1687653079896483135769135784451125398975732275358080312084893914240056843079", 10) - feltSExpected := caigotypes.BigToFelt(bigSExpected) + feltSExpected := new(felt.Felt).SetBytes(bigSExpected.Bytes()) assert.NotEqual(t, otherS, s, "signature not in canonical form") assert.Equal(t, feltSExpected, s) } diff --git a/core/services/keystore/keys/starkkey/utils.go b/core/services/keystore/keys/starkkey/utils.go index 19ba54799d3..d8706ba9dbc 100644 --- a/core/services/keystore/keys/starkkey/utils.go +++ b/core/services/keystore/keys/starkkey/utils.go @@ -6,7 +6,7 @@ import ( "io" "math/big" - "github.com/smartcontractkit/caigo" + "github.com/NethermindEth/starknet.go/curve" ) // constants @@ -14,23 +14,24 @@ var ( byteLen = 32 ) -// reimplements parts of https://github.com/smartcontractkit/caigo/blob/main/utils.go#L85 +// reimplements parts of +// https://github.com/NethermindEth/starknet.go/blob/0bdaab716ce24a521304744a8fbd8e01800c241d/curve/curve.go#L702 // generate the PK as a pseudo-random number in the interval [1, CurveOrder - 1] // using io.Reader, and Key struct func GenerateKey(material io.Reader) (k Key, err error) { - max := new(big.Int).Sub(caigo.Curve.N, big.NewInt(1)) + max := new(big.Int).Sub(curve.Curve.N, big.NewInt(1)) k.priv, err = rand.Int(material, max) if err != nil { return k, err } - k.pub.X, k.pub.Y, err = caigo.Curve.PrivateToPoint(k.priv) + k.pub.X, k.pub.Y, err = curve.Curve.PrivateToPoint(k.priv) if err != nil { return k, err } - if !caigo.Curve.IsOnCurve(k.pub.X, k.pub.Y) { + if !curve.Curve.IsOnCurve(k.pub.X, k.pub.Y) { return k, fmt.Errorf("key gen is not on stark curve") } diff --git a/core/services/keystore/starknet.go b/core/services/keystore/starknet.go index 251c74d0e00..6b6afa987c6 100644 --- a/core/services/keystore/starknet.go +++ b/core/services/keystore/starknet.go @@ -7,7 +7,7 @@ import ( "github.com/pkg/errors" - "github.com/smartcontractkit/caigo" + "github.com/NethermindEth/starknet.go/curve" "github.com/smartcontractkit/chainlink-common/pkg/loop" adapters "github.com/smartcontractkit/chainlink-common/pkg/loop/adapters/starknet" @@ -179,7 +179,7 @@ func (lk *StarknetLooppSigner) Sign(ctx context.Context, id string, hash []byte) } starkHash := new(big.Int).SetBytes(hash) - x, y, err := caigo.Curve.Sign(starkHash, k.ToPrivKey()) + x, y, err := curve.Curve.Sign(starkHash, k.ToPrivKey()) if err != nil { return nil, fmt.Errorf("error signing data with curve: %w", err) } diff --git a/core/services/keystore/starknet_test.go b/core/services/keystore/starknet_test.go index a007b01f120..43624a4159e 100644 --- a/core/services/keystore/starknet_test.go +++ b/core/services/keystore/starknet_test.go @@ -9,7 +9,7 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/smartcontractkit/caigo" + "github.com/NethermindEth/starknet.go/curve" "github.com/smartcontractkit/chainlink-common/pkg/utils" "github.com/smartcontractkit/chainlink/v2/core/internal/cltest" @@ -138,15 +138,15 @@ func TestStarknetSigner(t *testing.T) { adapter := starktxm.NewKeystoreAdapter(lk) baseKs.On("Get", starknetSenderAddr).Return(starkKey, nil) - hash, err := caigo.Curve.PedersenHash([]*big.Int{big.NewInt(42)}) + hash, err := curve.Curve.PedersenHash([]*big.Int{big.NewInt(42)}) require.NoError(t, err) r, s, err := adapter.Sign(testutils.Context(t), starknetSenderAddr, hash) require.NoError(t, err) require.NotNil(t, r) require.NotNil(t, s) - pubx, puby, err := caigo.Curve.PrivateToPoint(starkKey.ToPrivKey()) + pubx, puby, err := curve.Curve.PrivateToPoint(starkKey.ToPrivKey()) require.NoError(t, err) - require.True(t, caigo.Curve.Verify(hash, r, s, pubx, puby)) + require.True(t, curve.Curve.Verify(hash, r, s, pubx, puby)) }) } diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go index bb6bd3c0aff..206932cf543 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry.go @@ -6,6 +6,7 @@ import ( "fmt" "math/big" "net/http" + "strings" "sync" "time" @@ -90,12 +91,7 @@ func NewEvmRegistry( blockSub *BlockSubscriber, finalityDepth uint32, ) *EvmRegistry { - mercuryConfig := &MercuryConfig{ - cred: mc, - Abi: core.StreamsCompatibleABI, - AllowListCache: cache.New(defaultAllowListExpiration, cleanupInterval), - pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval), - } + mercuryConfig := NewMercuryConfig(mc, core.StreamsCompatibleABI) hc := http.DefaultClient return &EvmRegistry{ @@ -138,9 +134,16 @@ type MercuryConfig struct { pluginRetryCache *cache.Cache } -func NewMercuryConfig(credentials *types.MercuryCredentials, abi abi.ABI) *MercuryConfig { +func NewMercuryConfig(cred *types.MercuryCredentials, abi abi.ABI) *MercuryConfig { + c := &types.MercuryCredentials{} + if cred != nil { + c.Password = cred.Password + c.Username = cred.Username + c.URL = strings.TrimRight(cred.URL, "/") + c.LegacyURL = strings.TrimRight(cred.LegacyURL, "/") + } return &MercuryConfig{ - cred: credentials, + cred: c, Abi: abi, AllowListCache: cache.New(defaultPluginRetryExpiration, cleanupInterval), pluginRetryCache: cache.New(defaultPluginRetryExpiration, cleanupInterval), diff --git a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go index 024c5e79925..4dcb72fde86 100644 --- a/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go +++ b/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/registry_test.go @@ -8,14 +8,15 @@ import ( "testing" "time" - types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" coreTypes "github.com/ethereum/go-ethereum/core/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" + types2 "github.com/smartcontractkit/chainlink-automation/pkg/v3/types" + "github.com/smartcontractkit/chainlink-common/pkg/types" + types3 "github.com/smartcontractkit/chainlink/v2/core/chains/evm/headtracker/types" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller" "github.com/smartcontractkit/chainlink/v2/core/chains/evm/logpoller/mocks" @@ -29,6 +30,49 @@ import ( "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/logprovider" ) +func TestMercuryConfig_RemoveTrailingSlash(t *testing.T) { + tests := []struct { + Name string + URL string + LegacyURL string + }{ + { + Name: "Both have trailing slashes", + URL: "http://example.com/", + LegacyURL: "http://legacy.example.com/", + }, + { + Name: "One has trailing slashes", + URL: "http://example.com", + LegacyURL: "http://legacy.example.com/", + }, + { + Name: "Neither has trailing slashes", + URL: "http://example.com", + LegacyURL: "http://legacy.example.com", + }, + } + + for _, test := range tests { + t.Run(test.Name, func(t *testing.T) { + mockConfig := NewMercuryConfig(&types.MercuryCredentials{ + URL: test.URL, + LegacyURL: test.LegacyURL, + Username: "user", + Password: "pass", + }, core.StreamsCompatibleABI) + + result := mockConfig.Credentials() + + // Assert that trailing slashes are removed + assert.Equal(t, "http://example.com", result.URL) + assert.Equal(t, "http://legacy.example.com", result.LegacyURL) + assert.Equal(t, "user", result.Username) + assert.Equal(t, "pass", result.Password) + }) + } +} + func TestPollLogs(t *testing.T) { tests := []struct { Name string diff --git a/core/services/ocrcommon/data_source.go b/core/services/ocrcommon/data_source.go index 011b8d0644d..f810c8e044d 100644 --- a/core/services/ocrcommon/data_source.go +++ b/core/services/ocrcommon/data_source.go @@ -101,6 +101,7 @@ func NewInMemoryDataSource(pr pipeline.Runner, jb job.Job, spec pipeline.Spec, l } const defaultCacheFreshness = time.Minute * 5 +const defaultCacheFreshnessAlert = time.Hour * 24 const dataSourceCacheKey = "dscache" func NewInMemoryDataSourceCache(ds median.DataSource, kvStore job.KVStore, cacheFreshness time.Duration) (median.DataSource, error) { @@ -158,7 +159,7 @@ func (ds *inMemoryDataSource) currentAnswer() (*big.Int, *big.Int) { func (ds *inMemoryDataSource) executeRun(ctx context.Context) (*pipeline.Run, pipeline.TaskRunResults, error) { md, err := bridges.MarshalBridgeMetaData(ds.currentAnswer()) if err != nil { - ds.lggr.Warnw("unable to attach metadata for run", "err", err) + ds.lggr.Warnf("unable to attach metadata for run, err: %v", err) } vars := pipeline.NewVarsFrom(map[string]interface{}{ @@ -236,12 +237,17 @@ func (ds *inMemoryDataSourceCache) updater() { for ; true; <-ticker.C { ctx, cancel := context.WithTimeout(context.Background(), time.Second*10) if err := ds.updateCache(ctx); err != nil { - ds.lggr.Warnf("failed to update cache", "err", err) + ds.lggr.Warnf("failed to update cache, err: %v", err) } cancel() } } +type ResultTimePair struct { + Result serializablebig.Big `json:"result"` + Time time.Time `json:"time"` +} + func (ds *inMemoryDataSourceCache) updateCache(ctx context.Context) error { ds.mu.Lock() defer ds.mu.Unlock() @@ -257,7 +263,7 @@ func (ds *inMemoryDataSourceCache) updateCache(ctx context.Context) error { ds.latestUpdateErr = latestUpdateErr // raise log severity if previousUpdateErr != nil { - ds.lggr.Errorf("consecutive cache updates errored: previous err: %w new err: %w", previousUpdateErr, ds.latestUpdateErr) + ds.lggr.Warnf("consecutive cache updates errored: previous err: %v new err: %v", previousUpdateErr, ds.latestUpdateErr) } return errors.Wrapf(ds.latestUpdateErr, "error executing run for spec ID %v", ds.spec.ID) } @@ -270,8 +276,8 @@ func (ds *inMemoryDataSourceCache) updateCache(ctx context.Context) error { } // backup in case data source fails continuously and node gets rebooted - if err = ds.kvStore.Store(dataSourceCacheKey, serializablebig.New(value)); err != nil { - ds.lggr.Errorf("failed to persist latest task run value", err) + if err = ds.kvStore.Store(dataSourceCacheKey, &ResultTimePair{Result: *serializablebig.New(value), Time: time.Now()}); err != nil { + ds.lggr.Errorf("failed to persist latest task run value, err: %v", err) } return nil @@ -287,7 +293,7 @@ func (ds *inMemoryDataSourceCache) get(ctx context.Context) (pipeline.FinalResul ds.mu.RUnlock() if err := ds.updateCache(ctx); err != nil { - ds.lggr.Warnf("failed to update cache, returning stale result now", "err", err) + ds.lggr.Warnf("failed to update cache err: %v, returning stale result now, err: %v", err) } ds.mu.RLock() @@ -296,11 +302,17 @@ func (ds *inMemoryDataSourceCache) get(ctx context.Context) (pipeline.FinalResul } func (ds *inMemoryDataSourceCache) Observe(ctx context.Context, timestamp ocr2types.ReportTimestamp) (*big.Int, error) { - var val serializablebig.Big + var resTime ResultTimePair latestResult, latestTrrs := ds.get(ctx) if latestTrrs == nil { - ds.lggr.Errorf("cache is empty, returning persisted value now") - return val.ToInt(), ds.kvStore.Get(dataSourceCacheKey, &val) + ds.lggr.Warnf("cache is empty, returning persisted value now") + if err := ds.kvStore.Get(dataSourceCacheKey, &resTime); err != nil { + return nil, err + } + if time.Since(resTime.Time) >= defaultCacheFreshnessAlert { + ds.lggr.Errorf("cache hasn't been updated for over %v, latestUpdateErr is: %v", defaultCacheFreshnessAlert, ds.latestUpdateErr) + } + return resTime.Result.ToInt(), nil } setEATelemetry(ds.inMemoryDataSource, latestResult, latestTrrs, ObservationTimestamp{ diff --git a/core/services/ocrcommon/data_source_test.go b/core/services/ocrcommon/data_source_test.go index a921bc060ff..2e1b4f63df7 100644 --- a/core/services/ocrcommon/data_source_test.go +++ b/core/services/ocrcommon/data_source_test.go @@ -75,7 +75,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { ds := ocrcommon.NewInMemoryDataSource(runner, job.Job{}, pipeline.Spec{}, logger.TestLogger(t)) mockKVStore := mocks.KVStore{} mockKVStore.On("Store", mock.Anything, mock.Anything).Return(nil) - mockKVStore.On("Get", mock.Anything, mock.AnythingOfType("*big.Big")).Return(nil) + mockKVStore.On("Get", mock.Anything, mock.IsType(&ocrcommon.ResultTimePair{})).Return(nil) dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, time.Second*2) require.NoError(t, err) @@ -98,14 +98,14 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { }) t.Run("test total updater fail with persisted value recovery", func(t *testing.T) { - persistedVal := big.NewInt(1337) runner := pipelinemocks.NewRunner(t) ds := ocrcommon.NewInMemoryDataSource(runner, job.Job{}, pipeline.Spec{}, logger.TestLogger(t)) mockKVStore := mocks.KVStore{} - mockKVStore.On("Get", mock.Anything, mock.AnythingOfType("*big.Big")).Return(nil).Run(func(args mock.Arguments) { - arg := args.Get(1).(*serializablebig.Big) - arg.ToInt().Set(persistedVal) + persistedVal := serializablebig.NewI(1337) + mockKVStore.On("Get", mock.Anything, mock.IsType(&ocrcommon.ResultTimePair{})).Return(nil).Run(func(args mock.Arguments) { + arg := args.Get(1).(*ocrcommon.ResultTimePair) + arg.Result = *persistedVal }) // set updater to a long time so that it doesn't log errors after the test is done @@ -125,7 +125,7 @@ func Test_CachedInMemoryDataSourceErrHandling(t *testing.T) { ds := ocrcommon.NewInMemoryDataSource(runner, job.Job{}, pipeline.Spec{}, logger.TestLogger(t)) mockKVStore := mocks.KVStore{} - mockKVStore.On("Get", mock.Anything, mock.AnythingOfType("*big.Big")).Return(nil).Return(assert.AnError) + mockKVStore.On("Get", mock.Anything, mock.IsType(&ocrcommon.ResultTimePair{})).Return(nil).Return(assert.AnError) // set updater to a long time so that it doesn't log errors after the test is done dsCache, err := ocrcommon.NewInMemoryDataSourceCache(ds, &mockKVStore, time.Hour*100) diff --git a/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml new file mode 100644 index 00000000000..0fab758ac44 --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/marshalling/workflow_1.yaml @@ -0,0 +1,88 @@ + triggers: + - type: on_mercury_report@1 + ref: report_data + config: + boolean_coercion: + bools: + - y + - n + - yes + - no + - Y + - N + - YES + - NO + - No + - Yes + - TRUE + - FALSE + - True + - False + - true + - false + strings: + - TruE + - FalsE + - "true" + - "false" + - "TRUE" + - "FALSE" + - t + - f + - "T" + - "F" + - "t" + - "f" + - "1" + - "0" + - "yes" + - "no" + - "y" + - "n" + - "YES" + - "NO" + - "Y" + - "N" + numbers: + - 1 + - 0 + feed_ids: + - 123 # ETHUSD + - 456 # LINKUSD + - 789 # USDBTC + + # no actions + + consensus: + - type: offchain_reporting@1 + inputs: + observations: + - triggers.report_data.outputs + config: + aggregation_method: data_feeds_2_0 + aggregation_config: + 123: # ETHUSD + deviation: "0.005" + heartbeat: 24h + test: + 456: # LINKUSD + deviation: "0.001" + heartbeat: 24h + 789: # USDBTC + deviation: "0.002" + heartbeat: 6h + encoder: EVM + encoder_config: + abi: "mercury_reports bytes[]" + + targets: + - type: write_polygon_mainnet@1 + inputs: + report: + - consensus.evm_median.outputs.report + config: + address: "0xaabbcc" + method: "updateFeedValues(report bytes, role uint8)" + params: [$(inputs.report), 1] + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml new file mode 100644 index 00000000000..67d6890c47b --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/references/failing_1.yaml @@ -0,0 +1,15 @@ +triggers: +- type: trigger_test@1 + config: {} + +consensus: + - type: offchain_reporting@1 + ref: offchain_reporting=1 + config: {} + +targets: + - type: write_polygon_mainnet@1 + ref: write_polygon_mainnet_1 + config: {} + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml new file mode 100644 index 00000000000..f8c7d20136e --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/references/passing_1.yaml @@ -0,0 +1,15 @@ +triggers: +- type: trigger_test@1 + config: {} + +consensus: + - type: offchain_reporting@1 + ref: offchain_reporting_1 + config: {} + +targets: + - type: write_polygon_mainnet@1 + ref: write_polygon_mainnet_1 + config: {} + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml new file mode 100644 index 00000000000..b45676388c5 --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_1.yaml @@ -0,0 +1,16 @@ +# Should fail since version is more specific than major +triggers: + - type: trigger_test@1.0 + config: {} + +consensus: + - type: offchain_reporting@1 + ref: offchain_reporting_1 + config: {} + +targets: + - type: write_polygon_mainnet@1 + ref: write_polygon_mainnet_1 + config: {} + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml new file mode 100644 index 00000000000..c2a1872b4cf --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/failing_2.yaml @@ -0,0 +1,17 @@ + +# Should fail since version is more specific than major +triggers: + - type: trigger_test@1.0.0 + config: {} + +consensus: + - type: offchain_reporting@1 + ref: offchain_reporting_1 + config: {} + +targets: + - type: write_polygon_mainnet@1 + ref: write_polygon_mainnet_1 + config: {} + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml new file mode 100644 index 00000000000..83bdcc610ef --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/versioning/passing_1.yaml @@ -0,0 +1,15 @@ + triggers: + - type: trigger_test@1 + config: {} + + consensus: + - type: offchain_reporting@1-beta.1 + ref: offchain_reporting_1 + config: {} + + targets: + - type: write_polygon_mainnet@1-alpha+sha246er3 + ref: write_polygon_mainnet_1 + config: {} + +# yaml-language-server: $schema=../workflow_schema.json diff --git a/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json new file mode 100644 index 00000000000..221e4582d19 --- /dev/null +++ b/core/services/workflows/testdata/fixtures/workflows/workflow_schema.json @@ -0,0 +1,66 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://github.com/smartcontractkit/chainlink/v2/core/services/workflows/workflow-spec", + "$ref": "#/$defs/workflowSpec", + "$defs": { + "stepDefinition": { + "properties": { + "type": { + "type": "string", + "pattern": "^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" + }, + "ref": { + "type": "string", + "pattern": "^[a-z0-9_]+$" + }, + "inputs": { + "type": "object" + }, + "config": { + "type": "object" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "type", + "config" + ] + }, + "workflowSpec": { + "properties": { + "triggers": { + "items": { + "$ref": "#/$defs/stepDefinition" + }, + "type": "array" + }, + "actions": { + "items": { + "$ref": "#/$defs/stepDefinition" + }, + "type": "array" + }, + "consensus": { + "items": { + "$ref": "#/$defs/stepDefinition" + }, + "type": "array" + }, + "targets": { + "items": { + "$ref": "#/$defs/stepDefinition" + }, + "type": "array" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "triggers", + "consensus", + "targets" + ] + } + } +} \ No newline at end of file diff --git a/core/services/workflows/workflow.go b/core/services/workflows/workflow.go index f6731a937db..11f655d36f9 100644 --- a/core/services/workflows/workflow.go +++ b/core/services/workflows/workflow.go @@ -1,11 +1,12 @@ package workflows import ( + "encoding/json" "fmt" - "gopkg.in/yaml.v3" - "github.com/dominikbraun/graph" + "github.com/invopop/jsonschema" + "sigs.k8s.io/yaml" "github.com/smartcontractkit/chainlink-common/pkg/capabilities" "github.com/smartcontractkit/chainlink-common/pkg/values" @@ -17,19 +18,101 @@ type stepRequest struct { } // stepDefinition is the parsed representation of a step in a workflow. +// +// Within the workflow spec, they are called "Capability Properties". type stepDefinition struct { - Type string `yaml:"type"` - Ref string `yaml:"ref"` - Inputs map[string]any `yaml:"inputs"` - Config map[string]any `yaml:"config"` + // A universally unique name for a capability will be defined under the “type” property. The uniqueness will, eventually, be enforced in the Capability Registry . Semver must be used to specify the version of the Capability at the end of the type field. Capability versions must be immutable. + // + // Initially, we will require major versions. This will ease upgrades early on while we develop the infrastructure. + // + // Eventually, we might support minor version and specific version pins. This will allow workflow authors to have flexibility when selecting the version, and node operators will be able to determine when they should update their capabilities. + // + // There are two ways to specify a type - using a string as a fully qualified ID or a structured table. When using a table, tags are ordered alphanumerically and joined into a string following a + // {type}:{tag1_key}_{tag1_value}:{tag2_key}_{tag2_value}@{version} + // pattern. + // + // The “type” supports [a-z0-9_-:] characters followed by an @ and [semver regex] at the end. + // + // Validation must throw an error if: + // + // Unsupported characters are used. + // (For Keystone only.) More specific than a major version is specified. + // + // Example (string) + // type: read_chain:chain_ethereum:network_mainnet@1 + // + // Example (table) + // + // type: + // name: read_chain + // version: 1 + // tags: + // chain: ethereum + // network: mainnet + // + // [semver regex]: https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + Type string `json:"type" jsonschema:"required,pattern=^[a-z0-9_\\-:]+@(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$"` + + // Actions and Consensus capabilities have a required “ref” property that must be unique within a Workflow file (not universally) This property enables referencing outputs and is required because Actions and Consensus always need to be referenced in the following phases. Triggers can optionally specify if they need to be referenced. + // + // The “ref” supports [a-z0-9_] characters. + // + // Validation must throw an error if: + // - Unsupported characters are used. + // - The same “ref” appears in the workflow multiple times. + // - “ref” is used on a Target capability. + // - “ref” has a circular reference. + // + // NOTE: Should introduce a custom validator to cover trigger case + Ref string `json:"ref,omitempty" jsonschema:"pattern=^[a-z0-9_]+$"` + + // Capabilities can specify an additional optional ”inputs” property. It allows specifying a dependency on the result of one or more other capabilities. These are always runtime values that cannot be provided upfront. It takes a map of the argument name internal to the capability and an explicit reference to the values. + // + // References are specified using the [type].[ref].[path_to_value] pattern. + // + // The interpolation of “inputs” is allowed + // + // Validation must throw an error if: + // - Input reference cannot be resolved. + // - Input is defined on triggers + // NOTE: Should introduce a custom validator to cover trigger case + Inputs map[string]any `json:"inputs,omitempty"` + + // The configuration of a Capability will be done using the “config” property. Each capability is responsible for defining an external interface used during setup. This interface may be unique or identical, meaning multiple Capabilities might use the same configuration properties. + // + // The interpolation of “inputs” + // + // Interpolation of self inputs is allowed from within the “config” property. + // + // Example + // targets: + // - type: write_polygon_mainnet@1 + // inputs: + // report: + // - consensus.evm_median.outputs.report + // config: + // address: "0xaabbcc" + // method: "updateFeedValues(report bytes, role uint8)" + // params: [$(inputs.report), 1] + Config map[string]any `json:"config" jsonschema:"required"` } // workflowSpec is the parsed representation of a workflow. type workflowSpec struct { - Triggers []stepDefinition `yaml:"triggers"` - Actions []stepDefinition `yaml:"actions"` - Consensus []stepDefinition `yaml:"consensus"` - Targets []stepDefinition `yaml:"targets"` + // Triggers define a starting condition for the workflow, based on specific events or conditions. + Triggers []stepDefinition `json:"triggers" jsonschema:"required"` + // Actions represent a discrete operation within the workflow, potentially transforming input data. + Actions []stepDefinition `json:"actions,omitempty"` + // Consensus encapsulates the logic for aggregating and validating the results from various nodes. + Consensus []stepDefinition `json:"consensus" jsonschema:"required"` + // Targets represents the final step of the workflow, delivering the processed data to a specified location. + Targets []stepDefinition `json:"targets" jsonschema:"required"` +} + +func GenerateJsonSchema() ([]byte, error) { + schema := jsonschema.Reflect(&workflowSpec{}) + + return json.MarshalIndent(schema, "", " ") } func (w *workflowSpec) steps() []stepDefinition { diff --git a/core/services/workflows/workflow_test.go b/core/services/workflows/workflow_test.go index 93b5bf64f56..f6a2df38e1c 100644 --- a/core/services/workflows/workflow_test.go +++ b/core/services/workflows/workflow_test.go @@ -1,12 +1,179 @@ package workflows import ( + "encoding/json" + "fmt" + "os" "testing" + "github.com/google/go-cmp/cmp" + "github.com/santhosh-tekuri/jsonschema/v5" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "sigs.k8s.io/yaml" ) +var fixtureDir = "./testdata/fixtures/workflows/" + +// yamlFixtureReaderObj reads a yaml fixture file and returns the parsed object +func yamlFixtureReaderObj(t *testing.T, testCase string) func(name string) any { + testFixtureReader := yamlFixtureReaderBytes(t, testCase) + + return func(name string) any { + testFileBytes := testFixtureReader(name) + + var testFileYaml any + err := yaml.Unmarshal(testFileBytes, &testFileYaml) + require.NoError(t, err) + + return testFileYaml + } +} + +// yamlFixtureReaderBytes reads a yaml fixture file and returns the bytes +func yamlFixtureReaderBytes(t *testing.T, testCase string) func(name string) []byte { + return func(name string) []byte { + testFileBytes, err := os.ReadFile(fmt.Sprintf(fixtureDir+"%s/%s.yaml", testCase, name)) + require.NoError(t, err) + + return testFileBytes + } +} + +var transformJSON = cmp.FilterValues(func(x, y []byte) bool { + return json.Valid(x) && json.Valid(y) +}, cmp.Transformer("ParseJSON", func(in []byte) (out interface{}) { + if err := json.Unmarshal(in, &out); err != nil { + panic(err) // should never occur given previous filter to ensure valid JSON + } + return out +})) + +func TestWorkflowSpecMarshalling(t *testing.T) { + workflowBytes := yamlFixtureReaderBytes(t, "marshalling")("workflow_1") + + spec := workflowSpec{} + err := yaml.Unmarshal(workflowBytes, &spec) + require.NoError(t, err) + + // Test that our workflowSpec still keeps all of the original data + var rawSpec interface{} + err = yaml.Unmarshal(workflowBytes, &rawSpec) + require.NoError(t, err) + + workflowspecJson, err := json.MarshalIndent(spec, "", " ") + require.NoError(t, err) + rawWorkflowSpecJson, err := json.MarshalIndent(rawSpec, "", " ") + require.NoError(t, err) + + if diff := cmp.Diff(rawWorkflowSpecJson, workflowspecJson, transformJSON); diff != "" { + t.Errorf("ParseWorkflowWorkflowSpecFromString() mismatch (-want +got):\n%s", diff) + t.FailNow() + } + + // Spot check some fields + consensusConfig := spec.Consensus[0].Config + v, ok := consensusConfig["aggregation_config"] + require.True(t, ok, "expected aggregation_config to be present in consensus config") + + // the type of the keys present in v should be string rather than a number + // this is because JSON keys are always strings + _, ok = v.(map[string]any) + require.True(t, ok, "expected map[string]interface{} but got %T", v) + + // Make sure we dont have any weird type coercion with possible boolean values + booleanCoercions, ok := spec.Triggers[0].Config["boolean_coercion"].(map[string]any) + require.True(t, ok, "expected boolean_coercion to be present in triggers config") + + // check bools + bools, ok := booleanCoercions["bools"] + require.True(t, ok, "expected bools to be present in boolean_coercions") + for _, v := range bools.([]interface{}) { + _, ok = v.(bool) + require.True(t, ok, "expected bool but got %T", v) + } + + // check strings + strings, ok := booleanCoercions["strings"] + require.True(t, ok, "expected strings to be present in boolean_coercions") + for _, v := range strings.([]interface{}) { + _, ok = v.(string) + require.True(t, ok, "expected string but got %T", v) + } + + // check numbers + numbers, ok := booleanCoercions["numbers"] + require.True(t, ok, "expected numbers to be present in boolean_coercions") + for _, v := range numbers.([]interface{}) { + _, ok = v.(float64) + require.True(t, ok, "expected float64 but got %T", v) + } +} + +func TestJsonSchema(t *testing.T) { + t.Run("GenerateJsonSchema", func(t *testing.T) { + expectedSchemaPath := fixtureDir + "workflow_schema.json" + generatedSchema, err := GenerateJsonSchema() + require.NoError(t, err) + + // change this to update golden file + shouldUpdateSchema := false + if shouldUpdateSchema { + err = os.WriteFile(expectedSchemaPath, generatedSchema, 0600) + require.NoError(t, err) + } + + expectedSchema, err := os.ReadFile(expectedSchemaPath) + require.NoError(t, err) + diff := cmp.Diff(expectedSchema, generatedSchema, transformJSON) + if diff != "" { + t.Errorf("GenerateJsonSchema() mismatch (-want +got):\n%s", diff) + t.FailNow() + } + }) + + t.Run("ValidateJsonSchema", func(t *testing.T) { + generatedSchema, err := GenerateJsonSchema() + require.NoError(t, err) + + // test version regex + // for keystone, we should support major versions only along with prereleases and build metadata + t.Run("version", func(t *testing.T) { + readVersionFixture := yamlFixtureReaderObj(t, "versioning") + failingFixture1 := readVersionFixture("failing_1") + failingFixture2 := readVersionFixture("failing_2") + passingFixture1 := readVersionFixture("passing_1") + jsonSchema, err := jsonschema.CompileString("github.com/smartcontractkit/chainlink", string(generatedSchema)) + require.NoError(t, err) + + err = jsonSchema.Validate(failingFixture1) + require.Error(t, err) + + err = jsonSchema.Validate(failingFixture2) + require.Error(t, err) + + err = jsonSchema.Validate(passingFixture1) + require.NoError(t, err) + }) + + // test ref regex + t.Run("ref", func(t *testing.T) { + readRefFixture := yamlFixtureReaderObj(t, "references") + failingFixture1 := readRefFixture("failing_1") + passingFixture1 := readRefFixture("passing_1") + jsonSchema, err := jsonschema.CompileString("github.com/smartcontractkit/chainlink", string(generatedSchema)) + require.NoError(t, err) + + err = jsonSchema.Validate(failingFixture1) + require.Error(t, err) + + err = jsonSchema.Validate(passingFixture1) + require.NoError(t, err) + }) + }) +} + func TestParse_Graph(t *testing.T) { testCases := []struct { name string diff --git a/core/web/assets/index.html b/core/web/assets/index.html index 21811e104e8..e7a6f061ef8 100644 --- a/core/web/assets/index.html +++ b/core/web/assets/index.html @@ -1 +1 @@ -Operator UIChainlink
\ No newline at end of file +Operator UIChainlink
\ No newline at end of file diff --git a/core/web/assets/index.html.gz b/core/web/assets/index.html.gz index 2067ae210af..f96298b4c84 100644 Binary files a/core/web/assets/index.html.gz and b/core/web/assets/index.html.gz differ diff --git a/core/web/assets/main.f42e73c0c7811e9907db.js b/core/web/assets/main.50e70a50a20fd1cb616f.js similarity index 93% rename from core/web/assets/main.f42e73c0c7811e9907db.js rename to core/web/assets/main.50e70a50a20fd1cb616f.js index 90276050fee..1845862825a 100644 --- a/core/web/assets/main.f42e73c0c7811e9907db.js +++ b/core/web/assets/main.50e70a50a20fd1cb616f.js @@ -184,4 +184,4 @@ object-assign */ Object.defineProperty(t,"__esModule",{value:!0}),"undefined"==typeof window||"function"!=typeof MessageChannel){var n,r,i,a,o,s=null,u=null,c=function(){if(null!==s)try{var e=t.unstable_now();s(!0,e),s=null}catch(n){throw setTimeout(c,0),n}},l=Date.now();t.unstable_now=function(){return Date.now()-l},n=function(e){null!==s?setTimeout(n,0,e):(s=e,setTimeout(c,0))},r=function(e,t){u=setTimeout(e,t)},i=function(){clearTimeout(u)},a=function(){return!1},o=t.unstable_forceFrameRate=function(){}}else{var f=window.performance,d=window.Date,h=window.setTimeout,p=window.clearTimeout;if("undefined"!=typeof console){var b=window.cancelAnimationFrame;"function"!=typeof window.requestAnimationFrame&&console.error("This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills"),"function"!=typeof b&&console.error("This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://fb.me/react-polyfills")}if("object"==typeof f&&"function"==typeof f.now)t.unstable_now=function(){return f.now()};else{var m=d.now();t.unstable_now=function(){return d.now()-m}}var g=!1,v=null,y=-1,w=5,_=0;a=function(){return t.unstable_now()>=_},o=function(){},t.unstable_forceFrameRate=function(e){0>e||125M(o,n))void 0!==u&&0>M(u,o)?(e[r]=u,e[s]=n,r=s):(e[r]=o,e[a]=n,r=a);else if(void 0!==u&&0>M(u,n))e[r]=u,e[s]=n,r=s;else break a}}return t}return null}function M(e,t){var n=e.sortIndex-t.sortIndex;return 0!==n?n:e.id-t.id}var O=[],A=[],L=1,C=null,I=3,D=!1,N=!1,P=!1;function R(e){for(var t=x(A);null!==t;){if(null===t.callback)T(A);else if(t.startTime<=e)T(A),t.sortIndex=t.expirationTime,k(O,t);else break;t=x(A)}}function j(e){if(P=!1,R(e),!N){if(null!==x(O))N=!0,n(F);else{var t=x(A);null!==t&&r(j,t.startTime-e)}}}function F(e,n){N=!1,P&&(P=!1,i()),D=!0;var o=I;try{for(R(n),C=x(O);null!==C&&(!(C.expirationTime>n)||e&&!a());){var s=C.callback;if(null!==s){C.callback=null,I=C.priorityLevel;var u=s(C.expirationTime<=n);n=t.unstable_now(),"function"==typeof u?C.callback=u:C===x(O)&&T(O),R(n)}else T(O);C=x(O)}if(null!==C)var c=!0;else{var l=x(A);null!==l&&r(j,l.startTime-n),c=!1}return c}finally{C=null,I=o,D=!1}}function Y(e){switch(e){case 1:return -1;case 2:return 250;case 5:return 1073741823;case 4:return 1e4;default:return 5e3}}var B=o;t.unstable_ImmediatePriority=1,t.unstable_UserBlockingPriority=2,t.unstable_NormalPriority=3,t.unstable_IdlePriority=5,t.unstable_LowPriority=4,t.unstable_runWithPriority=function(e,t){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var n=I;I=e;try{return t()}finally{I=n}},t.unstable_next=function(e){switch(I){case 1:case 2:case 3:var t=3;break;default:t=I}var n=I;I=t;try{return e()}finally{I=n}},t.unstable_scheduleCallback=function(e,a,o){var s=t.unstable_now();if("object"==typeof o&&null!==o){var u=o.delay;u="number"==typeof u&&0s?(e.sortIndex=u,k(A,e),null===x(O)&&e===x(A)&&(P?i():P=!0,r(j,u-s))):(e.sortIndex=o,k(O,e),N||D||(N=!0,n(F))),e},t.unstable_cancelCallback=function(e){e.callback=null},t.unstable_wrapCallback=function(e){var t=I;return function(){var n=I;I=t;try{return e.apply(this,arguments)}finally{I=n}}},t.unstable_getCurrentPriorityLevel=function(){return I},t.unstable_shouldYield=function(){var e=t.unstable_now();R(e);var n=x(O);return n!==C&&null!==C&&null!==n&&null!==n.callback&&n.startTime<=e&&n.expirationTime>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function c(e,t,n){var r=t.length-1;if(r=0?(i>0&&(e.lastNeed=i-1),i):--r=0?(i>0&&(e.lastNeed=i-2),i):--r=0?(i>0&&(2===i?i=0:e.lastNeed=i-3),i):0}function l(e,t,n){if((192&t[0])!=128)return e.lastNeed=0,"�";if(e.lastNeed>1&&t.length>1){if((192&t[1])!=128)return e.lastNeed=1,"�";if(e.lastNeed>2&&t.length>2&&(192&t[2])!=128)return e.lastNeed=2,"�"}}function f(e){var t=this.lastTotal-this.lastNeed,n=l(this,e,t);return void 0!==n?n:this.lastNeed<=e.length?(e.copy(this.lastChar,t,0,this.lastNeed),this.lastChar.toString(this.encoding,0,this.lastTotal)):void(e.copy(this.lastChar,t,0,e.length),this.lastNeed-=e.length)}function d(e,t){var n=c(this,e,t);if(!this.lastNeed)return e.toString("utf8",t);this.lastTotal=n;var r=e.length-(n-this.lastNeed);return e.copy(this.lastChar,0,r),e.toString("utf8",t,r)}function h(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+"�":t}function p(e,t){if((e.length-t)%2==0){var n=e.toString("utf16le",t);if(n){var r=n.charCodeAt(n.length-1);if(r>=55296&&r<=56319)return this.lastNeed=2,this.lastTotal=4,this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1],n.slice(0,-1)}return n}return this.lastNeed=1,this.lastTotal=2,this.lastChar[0]=e[e.length-1],e.toString("utf16le",t,e.length-1)}function b(e){var t=e&&e.length?this.write(e):"";if(this.lastNeed){var n=this.lastTotal-this.lastNeed;return t+this.lastChar.toString("utf16le",0,n)}return t}function m(e,t){var n=(e.length-t)%3;return 0===n?e.toString("base64",t):(this.lastNeed=3-n,this.lastTotal=3,1===n?this.lastChar[0]=e[e.length-1]:(this.lastChar[0]=e[e.length-2],this.lastChar[1]=e[e.length-1]),e.toString("base64",t,e.length-n))}function g(e){var t=e&&e.length?this.write(e):"";return this.lastNeed?t+this.lastChar.toString("base64",0,3-this.lastNeed):t}function v(e){return e.toString(this.encoding)}function y(e){return e&&e.length?this.write(e):""}t.s=s,s.prototype.write=function(e){var t,n;if(0===e.length)return"";if(this.lastNeed){if(void 0===(t=this.fillLast(e)))return"";n=this.lastNeed,this.lastNeed=0}else n=0;return nOF});var r,i,a,o,s,u,c,l=n(67294),f=n.t(l,2),d=n(97779),h=n(47886),p=n(57209),b=n(32316),m=n(95880),g=n(17051),v=n(71381),y=n(81701),w=n(3022),_=n(60323),E=n(87591),S=n(25649),k=n(28902),x=n(71426),T=n(48884),M=n(94184),O=n.n(M),A=n(55977),L=n(73935),C=function(){if("undefined"!=typeof Map)return Map;function e(e,t){var n=-1;return e.some(function(e,r){return e[0]===t&&(n=r,!0)}),n}return function(){function t(){this.__entries__=[]}return Object.defineProperty(t.prototype,"size",{get:function(){return this.__entries__.length},enumerable:!0,configurable:!0}),t.prototype.get=function(t){var n=e(this.__entries__,t),r=this.__entries__[n];return r&&r[1]},t.prototype.set=function(t,n){var r=e(this.__entries__,t);~r?this.__entries__[r][1]=n:this.__entries__.push([t,n])},t.prototype.delete=function(t){var n=this.__entries__,r=e(n,t);~r&&n.splice(r,1)},t.prototype.has=function(t){return!!~e(this.__entries__,t)},t.prototype.clear=function(){this.__entries__.splice(0)},t.prototype.forEach=function(e,t){void 0===t&&(t=null);for(var n=0,r=this.__entries__;n0},e.prototype.connect_=function(){I&&!this.connected_&&(document.addEventListener("transitionend",this.onTransitionEnd_),window.addEventListener("resize",this.refresh),Y?(this.mutationsObserver_=new MutationObserver(this.refresh),this.mutationsObserver_.observe(document,{attributes:!0,childList:!0,characterData:!0,subtree:!0})):(document.addEventListener("DOMSubtreeModified",this.refresh),this.mutationEventsAdded_=!0),this.connected_=!0)},e.prototype.disconnect_=function(){I&&this.connected_&&(document.removeEventListener("transitionend",this.onTransitionEnd_),window.removeEventListener("resize",this.refresh),this.mutationsObserver_&&this.mutationsObserver_.disconnect(),this.mutationEventsAdded_&&document.removeEventListener("DOMSubtreeModified",this.refresh),this.mutationsObserver_=null,this.mutationEventsAdded_=!1,this.connected_=!1)},e.prototype.onTransitionEnd_=function(e){var t=e.propertyName,n=void 0===t?"":t;F.some(function(e){return!!~n.indexOf(e)})&&this.refresh()},e.getInstance=function(){return this.instance_||(this.instance_=new e),this.instance_},e.instance_=null,e}(),U=function(e,t){for(var n=0,r=Object.keys(t);n0},e}(),er="undefined"!=typeof WeakMap?new WeakMap:new C,ei=function(){function e(t){if(!(this instanceof e))throw TypeError("Cannot call a class as a function.");if(!arguments.length)throw TypeError("1 argument required, but only 0 present.");var n=B.getInstance(),r=new en(t,n,this);er.set(this,r)}return e}();["observe","unobserve","disconnect"].forEach(function(e){ei.prototype[e]=function(){var t;return(t=er.get(this))[e].apply(t,arguments)}});var ea=void 0!==D.ResizeObserver?D.ResizeObserver:ei;let eo=ea;var es=function(e){var t=[],n=null,r=function(){for(var r=arguments.length,i=Array(r),a=0;a=t||n<0||f&&r>=a}function g(){var e=eb();if(m(e))return v(e);s=setTimeout(g,b(e))}function v(e){return(s=void 0,d&&r)?h(e):(r=i=void 0,o)}function y(){void 0!==s&&clearTimeout(s),c=0,r=u=i=s=void 0}function w(){return void 0===s?o:v(eb())}function _(){var e=eb(),n=m(e);if(r=arguments,i=this,u=e,n){if(void 0===s)return p(u);if(f)return clearTimeout(s),s=setTimeout(g,t),h(u)}return void 0===s&&(s=setTimeout(g,t)),o}return t=ez(t)||0,ed(n)&&(l=!!n.leading,a=(f="maxWait"in n)?eW(ez(n.maxWait)||0,t):a,d="trailing"in n?!!n.trailing:d),_.cancel=y,_.flush=w,_}let eq=eV;var eZ="Expected a function";function eX(e,t,n){var r=!0,i=!0;if("function"!=typeof e)throw TypeError(eZ);return ed(n)&&(r="leading"in n?!!n.leading:r,i="trailing"in n?!!n.trailing:i),eq(e,t,{leading:r,maxWait:t,trailing:i})}let eJ=eX;var eQ={debounce:eq,throttle:eJ},e1=function(e){return eQ[e]},e0=function(e){return"function"==typeof e},e2=function(){return"undefined"==typeof window},e3=function(e){return e instanceof Element||e instanceof HTMLDocument};function e4(e){return(e4="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function e5(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function e6(e,t){for(var n=0;ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&l.createElement(tG.Z,{variant:"indeterminate",classes:r}))};tK.propTypes={fetchCount:el().number.isRequired};let tV=(0,b.withStyles)(tW)(tK);var tq=n(5536);let tZ=n.p+"ba8bbf16ebf8e1d05bef.svg";function tX(){return(tX=Object.assign||function(e){for(var t=1;t120){for(var d=Math.floor(u/80),h=u%80,p=[],b=0;b0},name:{enumerable:!1},nodes:{enumerable:!1},source:{enumerable:!1},positions:{enumerable:!1},originalError:{enumerable:!1}}),null!=s&&s.stack)?(Object.defineProperty(nf(b),"stack",{value:s.stack,writable:!0,configurable:!0}),nl(b)):(Error.captureStackTrace?Error.captureStackTrace(nf(b),n):Object.defineProperty(nf(b),"stack",{value:Error().stack,writable:!0,configurable:!0}),b)}return ns(n,[{key:"toString",value:function(){return nw(this)}},{key:t4.YF,get:function(){return"Object"}}]),n}(nd(Error));function ny(e){return void 0===e||0===e.length?void 0:e}function nw(e){var t=e.message;if(e.nodes)for(var n=0,r=e.nodes;n",EOF:"",BANG:"!",DOLLAR:"$",AMP:"&",PAREN_L:"(",PAREN_R:")",SPREAD:"...",COLON:":",EQUALS:"=",AT:"@",BRACKET_L:"[",BRACKET_R:"]",BRACE_L:"{",PIPE:"|",BRACE_R:"}",NAME:"Name",INT:"Int",FLOAT:"Float",STRING:"String",BLOCK_STRING:"BlockString",COMMENT:"Comment"}),nx=n(10143),nT=Object.freeze({QUERY:"QUERY",MUTATION:"MUTATION",SUBSCRIPTION:"SUBSCRIPTION",FIELD:"FIELD",FRAGMENT_DEFINITION:"FRAGMENT_DEFINITION",FRAGMENT_SPREAD:"FRAGMENT_SPREAD",INLINE_FRAGMENT:"INLINE_FRAGMENT",VARIABLE_DEFINITION:"VARIABLE_DEFINITION",SCHEMA:"SCHEMA",SCALAR:"SCALAR",OBJECT:"OBJECT",FIELD_DEFINITION:"FIELD_DEFINITION",ARGUMENT_DEFINITION:"ARGUMENT_DEFINITION",INTERFACE:"INTERFACE",UNION:"UNION",ENUM:"ENUM",ENUM_VALUE:"ENUM_VALUE",INPUT_OBJECT:"INPUT_OBJECT",INPUT_FIELD_DEFINITION:"INPUT_FIELD_DEFINITION"}),nM=n(87392),nO=function(){function e(e){var t=new nS.WU(nk.SOF,0,0,0,0,null);this.source=e,this.lastToken=t,this.token=t,this.line=1,this.lineStart=0}var t=e.prototype;return t.advance=function(){return this.lastToken=this.token,this.token=this.lookahead()},t.lookahead=function(){var e,t=this.token;if(t.kind!==nk.EOF)do t=null!==(e=t.next)&&void 0!==e?e:t.next=nC(this,t);while(t.kind===nk.COMMENT)return t},e}();function nA(e){return e===nk.BANG||e===nk.DOLLAR||e===nk.AMP||e===nk.PAREN_L||e===nk.PAREN_R||e===nk.SPREAD||e===nk.COLON||e===nk.EQUALS||e===nk.AT||e===nk.BRACKET_L||e===nk.BRACKET_R||e===nk.BRACE_L||e===nk.PIPE||e===nk.BRACE_R}function nL(e){return isNaN(e)?nk.EOF:e<127?JSON.stringify(String.fromCharCode(e)):'"\\u'.concat(("00"+e.toString(16).toUpperCase()).slice(-4),'"')}function nC(e,t){for(var n=e.source,r=n.body,i=r.length,a=t.end;a31||9===a))return new nS.WU(nk.COMMENT,t,s,n,r,i,o.slice(t+1,s))}function nN(e,t,n,r,i,a){var o=e.body,s=n,u=t,c=!1;if(45===s&&(s=o.charCodeAt(++u)),48===s){if((s=o.charCodeAt(++u))>=48&&s<=57)throw n_(e,u,"Invalid number, unexpected digit after 0: ".concat(nL(s),"."))}else u=nP(e,u,s),s=o.charCodeAt(u);if(46===s&&(c=!0,s=o.charCodeAt(++u),u=nP(e,u,s),s=o.charCodeAt(u)),(69===s||101===s)&&(c=!0,(43===(s=o.charCodeAt(++u))||45===s)&&(s=o.charCodeAt(++u)),u=nP(e,u,s),s=o.charCodeAt(u)),46===s||nU(s))throw n_(e,u,"Invalid number, expected digit but got: ".concat(nL(s),"."));return new nS.WU(c?nk.FLOAT:nk.INT,t,u,r,i,a,o.slice(t,u))}function nP(e,t,n){var r=e.body,i=t,a=n;if(a>=48&&a<=57){do a=r.charCodeAt(++i);while(a>=48&&a<=57)return i}throw n_(e,i,"Invalid number, expected digit but got: ".concat(nL(a),"."))}function nR(e,t,n,r,i){for(var a=e.body,o=t+1,s=o,u=0,c="";o=48&&e<=57?e-48:e>=65&&e<=70?e-55:e>=97&&e<=102?e-87:-1}function nB(e,t,n,r,i){for(var a=e.body,o=a.length,s=t+1,u=0;s!==o&&!isNaN(u=a.charCodeAt(s))&&(95===u||u>=48&&u<=57||u>=65&&u<=90||u>=97&&u<=122);)++s;return new nS.WU(nk.NAME,t,s,n,r,i,a.slice(t,s))}function nU(e){return 95===e||e>=65&&e<=90||e>=97&&e<=122}function nH(e,t){return new n$(e,t).parseDocument()}var n$=function(){function e(e,t){var n=(0,nx.T)(e)?e:new nx.H(e);this._lexer=new nO(n),this._options=t}var t=e.prototype;return t.parseName=function(){var e=this.expectToken(nk.NAME);return{kind:nE.h.NAME,value:e.value,loc:this.loc(e)}},t.parseDocument=function(){var e=this._lexer.token;return{kind:nE.h.DOCUMENT,definitions:this.many(nk.SOF,this.parseDefinition,nk.EOF),loc:this.loc(e)}},t.parseDefinition=function(){if(this.peek(nk.NAME))switch(this._lexer.token.value){case"query":case"mutation":case"subscription":return this.parseOperationDefinition();case"fragment":return this.parseFragmentDefinition();case"schema":case"scalar":case"type":case"interface":case"union":case"enum":case"input":case"directive":return this.parseTypeSystemDefinition();case"extend":return this.parseTypeSystemExtension()}else if(this.peek(nk.BRACE_L))return this.parseOperationDefinition();else if(this.peekDescription())return this.parseTypeSystemDefinition();throw this.unexpected()},t.parseOperationDefinition=function(){var e,t=this._lexer.token;if(this.peek(nk.BRACE_L))return{kind:nE.h.OPERATION_DEFINITION,operation:"query",name:void 0,variableDefinitions:[],directives:[],selectionSet:this.parseSelectionSet(),loc:this.loc(t)};var n=this.parseOperationType();return this.peek(nk.NAME)&&(e=this.parseName()),{kind:nE.h.OPERATION_DEFINITION,operation:n,name:e,variableDefinitions:this.parseVariableDefinitions(),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseOperationType=function(){var e=this.expectToken(nk.NAME);switch(e.value){case"query":return"query";case"mutation":return"mutation";case"subscription":return"subscription"}throw this.unexpected(e)},t.parseVariableDefinitions=function(){return this.optionalMany(nk.PAREN_L,this.parseVariableDefinition,nk.PAREN_R)},t.parseVariableDefinition=function(){var e=this._lexer.token;return{kind:nE.h.VARIABLE_DEFINITION,variable:this.parseVariable(),type:(this.expectToken(nk.COLON),this.parseTypeReference()),defaultValue:this.expectOptionalToken(nk.EQUALS)?this.parseValueLiteral(!0):void 0,directives:this.parseDirectives(!0),loc:this.loc(e)}},t.parseVariable=function(){var e=this._lexer.token;return this.expectToken(nk.DOLLAR),{kind:nE.h.VARIABLE,name:this.parseName(),loc:this.loc(e)}},t.parseSelectionSet=function(){var e=this._lexer.token;return{kind:nE.h.SELECTION_SET,selections:this.many(nk.BRACE_L,this.parseSelection,nk.BRACE_R),loc:this.loc(e)}},t.parseSelection=function(){return this.peek(nk.SPREAD)?this.parseFragment():this.parseField()},t.parseField=function(){var e,t,n=this._lexer.token,r=this.parseName();return this.expectOptionalToken(nk.COLON)?(e=r,t=this.parseName()):t=r,{kind:nE.h.FIELD,alias:e,name:t,arguments:this.parseArguments(!1),directives:this.parseDirectives(!1),selectionSet:this.peek(nk.BRACE_L)?this.parseSelectionSet():void 0,loc:this.loc(n)}},t.parseArguments=function(e){var t=e?this.parseConstArgument:this.parseArgument;return this.optionalMany(nk.PAREN_L,t,nk.PAREN_R)},t.parseArgument=function(){var e=this._lexer.token,t=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.ARGUMENT,name:t,value:this.parseValueLiteral(!1),loc:this.loc(e)}},t.parseConstArgument=function(){var e=this._lexer.token;return{kind:nE.h.ARGUMENT,name:this.parseName(),value:(this.expectToken(nk.COLON),this.parseValueLiteral(!0)),loc:this.loc(e)}},t.parseFragment=function(){var e=this._lexer.token;this.expectToken(nk.SPREAD);var t=this.expectOptionalKeyword("on");return!t&&this.peek(nk.NAME)?{kind:nE.h.FRAGMENT_SPREAD,name:this.parseFragmentName(),directives:this.parseDirectives(!1),loc:this.loc(e)}:{kind:nE.h.INLINE_FRAGMENT,typeCondition:t?this.parseNamedType():void 0,directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(e)}},t.parseFragmentDefinition=function(){var e,t=this._lexer.token;return(this.expectKeyword("fragment"),(null===(e=this._options)||void 0===e?void 0:e.experimentalFragmentVariables)===!0)?{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),variableDefinitions:this.parseVariableDefinitions(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}:{kind:nE.h.FRAGMENT_DEFINITION,name:this.parseFragmentName(),typeCondition:(this.expectKeyword("on"),this.parseNamedType()),directives:this.parseDirectives(!1),selectionSet:this.parseSelectionSet(),loc:this.loc(t)}},t.parseFragmentName=function(){if("on"===this._lexer.token.value)throw this.unexpected();return this.parseName()},t.parseValueLiteral=function(e){var t=this._lexer.token;switch(t.kind){case nk.BRACKET_L:return this.parseList(e);case nk.BRACE_L:return this.parseObject(e);case nk.INT:return this._lexer.advance(),{kind:nE.h.INT,value:t.value,loc:this.loc(t)};case nk.FLOAT:return this._lexer.advance(),{kind:nE.h.FLOAT,value:t.value,loc:this.loc(t)};case nk.STRING:case nk.BLOCK_STRING:return this.parseStringLiteral();case nk.NAME:switch(this._lexer.advance(),t.value){case"true":return{kind:nE.h.BOOLEAN,value:!0,loc:this.loc(t)};case"false":return{kind:nE.h.BOOLEAN,value:!1,loc:this.loc(t)};case"null":return{kind:nE.h.NULL,loc:this.loc(t)};default:return{kind:nE.h.ENUM,value:t.value,loc:this.loc(t)}}case nk.DOLLAR:if(!e)return this.parseVariable()}throw this.unexpected()},t.parseStringLiteral=function(){var e=this._lexer.token;return this._lexer.advance(),{kind:nE.h.STRING,value:e.value,block:e.kind===nk.BLOCK_STRING,loc:this.loc(e)}},t.parseList=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseValueLiteral(e)};return{kind:nE.h.LIST,values:this.any(nk.BRACKET_L,r,nk.BRACKET_R),loc:this.loc(n)}},t.parseObject=function(e){var t=this,n=this._lexer.token,r=function(){return t.parseObjectField(e)};return{kind:nE.h.OBJECT,fields:this.any(nk.BRACE_L,r,nk.BRACE_R),loc:this.loc(n)}},t.parseObjectField=function(e){var t=this._lexer.token,n=this.parseName();return this.expectToken(nk.COLON),{kind:nE.h.OBJECT_FIELD,name:n,value:this.parseValueLiteral(e),loc:this.loc(t)}},t.parseDirectives=function(e){for(var t=[];this.peek(nk.AT);)t.push(this.parseDirective(e));return t},t.parseDirective=function(e){var t=this._lexer.token;return this.expectToken(nk.AT),{kind:nE.h.DIRECTIVE,name:this.parseName(),arguments:this.parseArguments(e),loc:this.loc(t)}},t.parseTypeReference=function(){var e,t=this._lexer.token;return(this.expectOptionalToken(nk.BRACKET_L)?(e=this.parseTypeReference(),this.expectToken(nk.BRACKET_R),e={kind:nE.h.LIST_TYPE,type:e,loc:this.loc(t)}):e=this.parseNamedType(),this.expectOptionalToken(nk.BANG))?{kind:nE.h.NON_NULL_TYPE,type:e,loc:this.loc(t)}:e},t.parseNamedType=function(){var e=this._lexer.token;return{kind:nE.h.NAMED_TYPE,name:this.parseName(),loc:this.loc(e)}},t.parseTypeSystemDefinition=function(){var e=this.peekDescription()?this._lexer.lookahead():this._lexer.token;if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaDefinition();case"scalar":return this.parseScalarTypeDefinition();case"type":return this.parseObjectTypeDefinition();case"interface":return this.parseInterfaceTypeDefinition();case"union":return this.parseUnionTypeDefinition();case"enum":return this.parseEnumTypeDefinition();case"input":return this.parseInputObjectTypeDefinition();case"directive":return this.parseDirectiveDefinition()}throw this.unexpected(e)},t.peekDescription=function(){return this.peek(nk.STRING)||this.peek(nk.BLOCK_STRING)},t.parseDescription=function(){if(this.peekDescription())return this.parseStringLiteral()},t.parseSchemaDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("schema");var n=this.parseDirectives(!0),r=this.many(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);return{kind:nE.h.SCHEMA_DEFINITION,description:t,directives:n,operationTypes:r,loc:this.loc(e)}},t.parseOperationTypeDefinition=function(){var e=this._lexer.token,t=this.parseOperationType();this.expectToken(nk.COLON);var n=this.parseNamedType();return{kind:nE.h.OPERATION_TYPE_DEFINITION,operation:t,type:n,loc:this.loc(e)}},t.parseScalarTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("scalar");var n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.SCALAR_TYPE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("type");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.OBJECT_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseImplementsInterfaces=function(){var e;if(!this.expectOptionalKeyword("implements"))return[];if((null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLImplementsInterfaces)===!0){var t=[];this.expectOptionalToken(nk.AMP);do t.push(this.parseNamedType());while(this.expectOptionalToken(nk.AMP)||this.peek(nk.NAME))return t}return this.delimitedMany(nk.AMP,this.parseNamedType)},t.parseFieldsDefinition=function(){var e;return(null===(e=this._options)||void 0===e?void 0:e.allowLegacySDLEmptyFields)===!0&&this.peek(nk.BRACE_L)&&this._lexer.lookahead().kind===nk.BRACE_R?(this._lexer.advance(),this._lexer.advance(),[]):this.optionalMany(nk.BRACE_L,this.parseFieldDefinition,nk.BRACE_R)},t.parseFieldDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseArgumentDefs();this.expectToken(nk.COLON);var i=this.parseTypeReference(),a=this.parseDirectives(!0);return{kind:nE.h.FIELD_DEFINITION,description:t,name:n,arguments:r,type:i,directives:a,loc:this.loc(e)}},t.parseArgumentDefs=function(){return this.optionalMany(nk.PAREN_L,this.parseInputValueDef,nk.PAREN_R)},t.parseInputValueDef=function(){var e,t=this._lexer.token,n=this.parseDescription(),r=this.parseName();this.expectToken(nk.COLON);var i=this.parseTypeReference();this.expectOptionalToken(nk.EQUALS)&&(e=this.parseValueLiteral(!0));var a=this.parseDirectives(!0);return{kind:nE.h.INPUT_VALUE_DEFINITION,description:n,name:r,type:i,defaultValue:e,directives:a,loc:this.loc(t)}},t.parseInterfaceTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("interface");var n=this.parseName(),r=this.parseImplementsInterfaces(),i=this.parseDirectives(!0),a=this.parseFieldsDefinition();return{kind:nE.h.INTERFACE_TYPE_DEFINITION,description:t,name:n,interfaces:r,directives:i,fields:a,loc:this.loc(e)}},t.parseUnionTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("union");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseUnionMemberTypes();return{kind:nE.h.UNION_TYPE_DEFINITION,description:t,name:n,directives:r,types:i,loc:this.loc(e)}},t.parseUnionMemberTypes=function(){return this.expectOptionalToken(nk.EQUALS)?this.delimitedMany(nk.PIPE,this.parseNamedType):[]},t.parseEnumTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("enum");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseEnumValuesDefinition();return{kind:nE.h.ENUM_TYPE_DEFINITION,description:t,name:n,directives:r,values:i,loc:this.loc(e)}},t.parseEnumValuesDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseEnumValueDefinition,nk.BRACE_R)},t.parseEnumValueDefinition=function(){var e=this._lexer.token,t=this.parseDescription(),n=this.parseName(),r=this.parseDirectives(!0);return{kind:nE.h.ENUM_VALUE_DEFINITION,description:t,name:n,directives:r,loc:this.loc(e)}},t.parseInputObjectTypeDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("input");var n=this.parseName(),r=this.parseDirectives(!0),i=this.parseInputFieldsDefinition();return{kind:nE.h.INPUT_OBJECT_TYPE_DEFINITION,description:t,name:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInputFieldsDefinition=function(){return this.optionalMany(nk.BRACE_L,this.parseInputValueDef,nk.BRACE_R)},t.parseTypeSystemExtension=function(){var e=this._lexer.lookahead();if(e.kind===nk.NAME)switch(e.value){case"schema":return this.parseSchemaExtension();case"scalar":return this.parseScalarTypeExtension();case"type":return this.parseObjectTypeExtension();case"interface":return this.parseInterfaceTypeExtension();case"union":return this.parseUnionTypeExtension();case"enum":return this.parseEnumTypeExtension();case"input":return this.parseInputObjectTypeExtension()}throw this.unexpected(e)},t.parseSchemaExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("schema");var t=this.parseDirectives(!0),n=this.optionalMany(nk.BRACE_L,this.parseOperationTypeDefinition,nk.BRACE_R);if(0===t.length&&0===n.length)throw this.unexpected();return{kind:nE.h.SCHEMA_EXTENSION,directives:t,operationTypes:n,loc:this.loc(e)}},t.parseScalarTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("scalar");var t=this.parseName(),n=this.parseDirectives(!0);if(0===n.length)throw this.unexpected();return{kind:nE.h.SCALAR_TYPE_EXTENSION,name:t,directives:n,loc:this.loc(e)}},t.parseObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("type");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.OBJECT_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseInterfaceTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("interface");var t=this.parseName(),n=this.parseImplementsInterfaces(),r=this.parseDirectives(!0),i=this.parseFieldsDefinition();if(0===n.length&&0===r.length&&0===i.length)throw this.unexpected();return{kind:nE.h.INTERFACE_TYPE_EXTENSION,name:t,interfaces:n,directives:r,fields:i,loc:this.loc(e)}},t.parseUnionTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("union");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseUnionMemberTypes();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.UNION_TYPE_EXTENSION,name:t,directives:n,types:r,loc:this.loc(e)}},t.parseEnumTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("enum");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseEnumValuesDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.ENUM_TYPE_EXTENSION,name:t,directives:n,values:r,loc:this.loc(e)}},t.parseInputObjectTypeExtension=function(){var e=this._lexer.token;this.expectKeyword("extend"),this.expectKeyword("input");var t=this.parseName(),n=this.parseDirectives(!0),r=this.parseInputFieldsDefinition();if(0===n.length&&0===r.length)throw this.unexpected();return{kind:nE.h.INPUT_OBJECT_TYPE_EXTENSION,name:t,directives:n,fields:r,loc:this.loc(e)}},t.parseDirectiveDefinition=function(){var e=this._lexer.token,t=this.parseDescription();this.expectKeyword("directive"),this.expectToken(nk.AT);var n=this.parseName(),r=this.parseArgumentDefs(),i=this.expectOptionalKeyword("repeatable");this.expectKeyword("on");var a=this.parseDirectiveLocations();return{kind:nE.h.DIRECTIVE_DEFINITION,description:t,name:n,arguments:r,repeatable:i,locations:a,loc:this.loc(e)}},t.parseDirectiveLocations=function(){return this.delimitedMany(nk.PIPE,this.parseDirectiveLocation)},t.parseDirectiveLocation=function(){var e=this._lexer.token,t=this.parseName();if(void 0!==nT[t.value])return t;throw this.unexpected(e)},t.loc=function(e){var t;if((null===(t=this._options)||void 0===t?void 0:t.noLocation)!==!0)return new nS.Ye(e,this._lexer.lastToken,this._lexer.source)},t.peek=function(e){return this._lexer.token.kind===e},t.expectToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t;throw n_(this._lexer.source,t.start,"Expected ".concat(nG(e),", found ").concat(nz(t),"."))},t.expectOptionalToken=function(e){var t=this._lexer.token;if(t.kind===e)return this._lexer.advance(),t},t.expectKeyword=function(e){var t=this._lexer.token;if(t.kind===nk.NAME&&t.value===e)this._lexer.advance();else throw n_(this._lexer.source,t.start,'Expected "'.concat(e,'", found ').concat(nz(t),"."))},t.expectOptionalKeyword=function(e){var t=this._lexer.token;return t.kind===nk.NAME&&t.value===e&&(this._lexer.advance(),!0)},t.unexpected=function(e){var t=null!=e?e:this._lexer.token;return n_(this._lexer.source,t.start,"Unexpected ".concat(nz(t),"."))},t.any=function(e,t,n){this.expectToken(e);for(var r=[];!this.expectOptionalToken(n);)r.push(t.call(this));return r},t.optionalMany=function(e,t,n){if(this.expectOptionalToken(e)){var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r}return[]},t.many=function(e,t,n){this.expectToken(e);var r=[];do r.push(t.call(this));while(!this.expectOptionalToken(n))return r},t.delimitedMany=function(e,t){this.expectOptionalToken(e);var n=[];do n.push(t.call(this));while(this.expectOptionalToken(e))return n},e}();function nz(e){var t=e.value;return nG(e.kind)+(null!=t?' "'.concat(t,'"'):"")}function nG(e){return nA(e)?'"'.concat(e,'"'):e}var nW=new Map,nK=new Map,nV=!0,nq=!1;function nZ(e){return e.replace(/[\s,]+/g," ").trim()}function nX(e){return nZ(e.source.body.substring(e.start,e.end))}function nJ(e){var t=new Set,n=[];return e.definitions.forEach(function(e){if("FragmentDefinition"===e.kind){var r=e.name.value,i=nX(e.loc),a=nK.get(r);a&&!a.has(i)?nV&&console.warn("Warning: fragment with name "+r+" already exists.\ngraphql-tag enforces all fragment names across your application to be unique; read more about\nthis in the docs: http://dev.apollodata.com/core/fragments.html#unique-names"):a||nK.set(r,a=new Set),a.add(i),t.has(i)||(t.add(i),n.push(e))}else n.push(e)}),(0,t0.pi)((0,t0.pi)({},e),{definitions:n})}function nQ(e){var t=new Set(e.definitions);t.forEach(function(e){e.loc&&delete e.loc,Object.keys(e).forEach(function(n){var r=e[n];r&&"object"==typeof r&&t.add(r)})});var n=e.loc;return n&&(delete n.startToken,delete n.endToken),e}function n1(e){var t=nZ(e);if(!nW.has(t)){var n=nH(e,{experimentalFragmentVariables:nq,allowLegacyFragmentVariables:nq});if(!n||"Document"!==n.kind)throw Error("Not a valid GraphQL document.");nW.set(t,nQ(nJ(n)))}return nW.get(t)}function n0(e){for(var t=[],n=1;n, or pass an ApolloClient instance in via options.'):(0,n7.kG)(!!n,32),n}var rb=n(10542),rm=n(53712),rg=n(21436),rv=Object.prototype.hasOwnProperty;function ry(e,t){return void 0===t&&(t=Object.create(null)),rw(rp(t.client),e).useQuery(t)}function rw(e,t){var n=(0,l.useRef)();n.current&&e===n.current.client&&t===n.current.query||(n.current=new r_(e,t,n.current));var r=n.current,i=(0,l.useState)(0),a=(i[0],i[1]);return r.forceUpdate=function(){a(function(e){return e+1})},r}var r_=function(){function e(e,t,n){this.client=e,this.query=t,this.ssrDisabledResult=(0,rb.J)({loading:!0,data:void 0,error:void 0,networkStatus:rc.I.loading}),this.skipStandbyResult=(0,rb.J)({loading:!1,data:void 0,error:void 0,networkStatus:rc.I.ready}),this.toQueryResultCache=new(re.mr?WeakMap:Map),rh(t,r.Query);var i=n&&n.result,a=i&&i.data;a&&(this.previousData=a)}return e.prototype.forceUpdate=function(){__DEV__&&n7.kG.warn("Calling default no-op implementation of InternalState#forceUpdate")},e.prototype.executeQuery=function(e){var t,n=this;e.query&&Object.assign(this,{query:e.query}),this.watchQueryOptions=this.createWatchQueryOptions(this.queryHookOptions=e);var r=this.observable.reobserveAsConcast(this.getObsQueryOptions());return this.previousData=(null===(t=this.result)||void 0===t?void 0:t.data)||this.previousData,this.result=void 0,this.forceUpdate(),new Promise(function(e){var t;r.subscribe({next:function(e){t=e},error:function(){e(n.toQueryResult(n.observable.getCurrentResult()))},complete:function(){e(n.toQueryResult(t))}})})},e.prototype.useQuery=function(e){var t=this;this.renderPromises=(0,l.useContext)((0,rs.K)()).renderPromises,this.useOptions(e);var n=this.useObservableQuery(),r=rn((0,l.useCallback)(function(){if(t.renderPromises)return function(){};var e=function(){var e=t.result,r=n.getCurrentResult();!(e&&e.loading===r.loading&&e.networkStatus===r.networkStatus&&(0,ra.D)(e.data,r.data))&&t.setResult(r)},r=function(a){var o=n.last;i.unsubscribe();try{n.resetLastResults(),i=n.subscribe(e,r)}finally{n.last=o}if(!rv.call(a,"graphQLErrors"))throw a;var s=t.result;(!s||s&&s.loading||!(0,ra.D)(a,s.error))&&t.setResult({data:s&&s.data,error:a,loading:!1,networkStatus:rc.I.error})},i=n.subscribe(e,r);return function(){return setTimeout(function(){return i.unsubscribe()})}},[n,this.renderPromises,this.client.disableNetworkFetches,]),function(){return t.getCurrentResult()},function(){return t.getCurrentResult()});return this.unsafeHandlePartialRefetch(r),this.toQueryResult(r)},e.prototype.useOptions=function(t){var n,r=this.createWatchQueryOptions(this.queryHookOptions=t),i=this.watchQueryOptions;!(0,ra.D)(r,i)&&(this.watchQueryOptions=r,i&&this.observable&&(this.observable.reobserve(this.getObsQueryOptions()),this.previousData=(null===(n=this.result)||void 0===n?void 0:n.data)||this.previousData,this.result=void 0)),this.onCompleted=t.onCompleted||e.prototype.onCompleted,this.onError=t.onError||e.prototype.onError,(this.renderPromises||this.client.disableNetworkFetches)&&!1===this.queryHookOptions.ssr&&!this.queryHookOptions.skip?this.result=this.ssrDisabledResult:this.queryHookOptions.skip||"standby"===this.watchQueryOptions.fetchPolicy?this.result=this.skipStandbyResult:(this.result===this.ssrDisabledResult||this.result===this.skipStandbyResult)&&(this.result=void 0)},e.prototype.getObsQueryOptions=function(){var e=[],t=this.client.defaultOptions.watchQuery;return t&&e.push(t),this.queryHookOptions.defaultOptions&&e.push(this.queryHookOptions.defaultOptions),e.push((0,rm.o)(this.observable&&this.observable.options,this.watchQueryOptions)),e.reduce(ro.J)},e.prototype.createWatchQueryOptions=function(e){void 0===e&&(e={});var t,n=e.skip,r=Object.assign((e.ssr,e.onCompleted,e.onError,e.defaultOptions,(0,n8._T)(e,["skip","ssr","onCompleted","onError","defaultOptions"])),{query:this.query});if(this.renderPromises&&("network-only"===r.fetchPolicy||"cache-and-network"===r.fetchPolicy)&&(r.fetchPolicy="cache-first"),r.variables||(r.variables={}),n){var i=r.fetchPolicy,a=void 0===i?this.getDefaultFetchPolicy():i,o=r.initialFetchPolicy;Object.assign(r,{initialFetchPolicy:void 0===o?a:o,fetchPolicy:"standby"})}else r.fetchPolicy||(r.fetchPolicy=(null===(t=this.observable)||void 0===t?void 0:t.options.initialFetchPolicy)||this.getDefaultFetchPolicy());return r},e.prototype.getDefaultFetchPolicy=function(){var e,t;return(null===(e=this.queryHookOptions.defaultOptions)||void 0===e?void 0:e.fetchPolicy)||(null===(t=this.client.defaultOptions.watchQuery)||void 0===t?void 0:t.fetchPolicy)||"cache-first"},e.prototype.onCompleted=function(e){},e.prototype.onError=function(e){},e.prototype.useObservableQuery=function(){var e=this.observable=this.renderPromises&&this.renderPromises.getSSRObservable(this.watchQueryOptions)||this.observable||this.client.watchQuery(this.getObsQueryOptions());this.obsQueryFields=(0,l.useMemo)(function(){return{refetch:e.refetch.bind(e),reobserve:e.reobserve.bind(e),fetchMore:e.fetchMore.bind(e),updateQuery:e.updateQuery.bind(e),startPolling:e.startPolling.bind(e),stopPolling:e.stopPolling.bind(e),subscribeToMore:e.subscribeToMore.bind(e)}},[e]);var t=!(!1===this.queryHookOptions.ssr||this.queryHookOptions.skip);return this.renderPromises&&t&&(this.renderPromises.registerSSRObservable(e),e.getCurrentResult().loading&&this.renderPromises.addObservableQueryPromise(e)),e},e.prototype.setResult=function(e){var t=this.result;t&&t.data&&(this.previousData=t.data),this.result=e,this.forceUpdate(),this.handleErrorOrCompleted(e)},e.prototype.handleErrorOrCompleted=function(e){var t=this;if(!e.loading){var n=this.toApolloError(e);Promise.resolve().then(function(){n?t.onError(n):e.data&&t.onCompleted(e.data)}).catch(function(e){__DEV__&&n7.kG.warn(e)})}},e.prototype.toApolloError=function(e){return(0,rg.O)(e.errors)?new ru.cA({graphQLErrors:e.errors}):e.error},e.prototype.getCurrentResult=function(){return this.result||this.handleErrorOrCompleted(this.result=this.observable.getCurrentResult()),this.result},e.prototype.toQueryResult=function(e){var t=this.toQueryResultCache.get(e);if(t)return t;var n=e.data,r=(e.partial,(0,n8._T)(e,["data","partial"]));return this.toQueryResultCache.set(e,t=(0,n8.pi)((0,n8.pi)((0,n8.pi)({data:n},r),this.obsQueryFields),{client:this.client,observable:this.observable,variables:this.observable.variables,called:!this.queryHookOptions.skip,previousData:this.previousData})),!t.error&&(0,rg.O)(e.errors)&&(t.error=new ru.cA({graphQLErrors:e.errors})),t},e.prototype.unsafeHandlePartialRefetch=function(e){e.partial&&this.queryHookOptions.partialRefetch&&!e.loading&&(!e.data||0===Object.keys(e.data).length)&&"cache-only"!==this.observable.options.fetchPolicy&&(Object.assign(e,{loading:!0,networkStatus:rc.I.refetch}),this.observable.refetch())},e}();function rE(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:{};return ry(i$,e)},iG=function(){var e=iF(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"50",10),r=iz({variables:{offset:(t-1)*n,limit:n},fetchPolicy:"network-only"}),i=r.data,a=r.loading,o=r.error;return a?l.createElement(ij,null):o?l.createElement(iN,{error:o}):i?l.createElement(iD,{chains:i.chains.results,page:t,pageSize:n,total:i.chains.metadata.total}):null},iW=n(67932),iK=n(8126),iV="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function iq(e){if(iZ())return Intl.DateTimeFormat.supportedLocalesOf(e)[0]}function iZ(){return("undefined"==typeof Intl?"undefined":iV(Intl))==="object"&&"function"==typeof Intl.DateTimeFormat}var iX="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},iJ=function(){function e(e,t){for(var n=0;n=i.length)break;s=i[o++]}else{if((o=i.next()).done)break;s=o.value}var s,u=s;if((void 0===e?"undefined":iX(e))!=="object")return;e=e[u]}return e}},{key:"put",value:function(){for(var e=arguments.length,t=Array(e),n=0;n=o.length)break;c=o[u++]}else{if((u=o.next()).done)break;c=u.value}var c,l=c;"object"!==iX(a[l])&&(a[l]={}),a=a[l]}return a[i]=r}}]),e}();let i0=i1;var i2=new i0;function i3(e,t){if(!iZ())return function(e){return e.toString()};var n=i5(e),r=JSON.stringify(t),i=i2.get(String(n),r)||i2.put(String(n),r,new Intl.DateTimeFormat(n,t));return function(e){return i.format(e)}}var i4={};function i5(e){var t=e.toString();return i4[t]?i4[t]:i4[t]=iq(e)}var i6="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};function i9(e){return i8(e)?e:new Date(e)}function i8(e){return e instanceof Date||i7(e)}function i7(e){return(void 0===e?"undefined":i6(e))==="object"&&"function"==typeof e.getTime}var ae=n(54087),at=n.n(ae);function an(e,t){if(0===e.length)return 0;for(var n=0,r=e.length-1,i=void 0;n<=r;){var a=t(e[i=Math.floor((r+n)/2)]);if(0===a)return i;if(a<0){if((n=i+1)>r)return n}else if((r=i-1)=t.nextUpdateTime)ao(t,this.instances);else break}},scheduleNextTick:function(){var e=this;this.scheduledTick=at()(function(){e.tick(),e.scheduleNextTick()})},start:function(){this.scheduleNextTick()},stop:function(){at().cancel(this.scheduledTick)}};function aa(e){var t=ar(e.getNextValue(),2),n=t[0],r=t[1];e.setValue(n),e.nextUpdateTime=r}function ao(e,t){aa(e),au(t,e),as(t,e)}function as(e,t){var n=ac(e,t);e.splice(n,0,t)}function au(e,t){var n=e.indexOf(t);e.splice(n,1)}function ac(e,t){var n=t.nextUpdateTime;return an(e,function(e){return e.nextUpdateTime===n?0:e.nextUpdateTime>n?1:-1})}var al=(0,ec.oneOfType)([(0,ec.shape)({minTime:ec.number,formatAs:ec.string.isRequired}),(0,ec.shape)({test:ec.func,formatAs:ec.string.isRequired}),(0,ec.shape)({minTime:ec.number,format:ec.func.isRequired}),(0,ec.shape)({test:ec.func,format:ec.func.isRequired})]),af=(0,ec.oneOfType)([ec.string,(0,ec.shape)({steps:(0,ec.arrayOf)(al).isRequired,labels:(0,ec.oneOfType)([ec.string,(0,ec.arrayOf)(ec.string)]).isRequired,round:ec.string})]),ad=Object.assign||function(e){for(var t=1;t=0)&&Object.prototype.hasOwnProperty.call(e,r)&&(n[r]=e[r]);return n}function ab(e){var t=e.date,n=e.future,r=e.timeStyle,i=e.round,a=e.minTimeLeft,o=e.tooltip,s=e.component,u=e.container,c=e.wrapperComponent,f=e.wrapperProps,d=e.locale,h=e.locales,p=e.formatVerboseDate,b=e.verboseDateFormat,m=e.updateInterval,g=e.tick,v=ap(e,["date","future","timeStyle","round","minTimeLeft","tooltip","component","container","wrapperComponent","wrapperProps","locale","locales","formatVerboseDate","verboseDateFormat","updateInterval","tick"]),y=(0,l.useMemo)(function(){return d&&(h=[d]),h.concat(iK.Z.getDefaultLocale())},[d,h]),w=(0,l.useMemo)(function(){return new iK.Z(y)},[y]);t=(0,l.useMemo)(function(){return i9(t)},[t]);var _=(0,l.useCallback)(function(){var e=Date.now(),o=void 0;if(n&&e>=t.getTime()&&(e=t.getTime(),o=!0),void 0!==a){var s=t.getTime()-1e3*a;e>s&&(e=s,o=!0)}var u=w.format(t,r,{getTimeToNextUpdate:!0,now:e,future:n,round:i}),c=ah(u,2),l=c[0],f=c[1];return f=o?av:m||f||6e4,[l,e+f]},[t,n,r,m,i,a,w]),E=(0,l.useRef)();E.current=_;var S=(0,l.useMemo)(_,[]),k=ah(S,2),x=k[0],T=k[1],M=(0,l.useState)(x),O=ah(M,2),A=O[0],L=O[1],C=ah((0,l.useState)(),2),I=C[0],D=C[1],N=(0,l.useRef)();(0,l.useEffect)(function(){if(g)return N.current=ai.add({getNextValue:function(){return E.current()},setValue:L,nextUpdateTime:T}),function(){return N.current.stop()}},[g]),(0,l.useEffect)(function(){if(N.current)N.current.forceUpdate();else{var e=_(),t=ah(e,1)[0];L(t)}},[_]),(0,l.useEffect)(function(){D(!0)},[]);var P=(0,l.useMemo)(function(){if("undefined"!=typeof window)return i3(y,b)},[y,b]),R=(0,l.useMemo)(function(){if("undefined"!=typeof window)return p?p(t):P(t)},[t,p,P]),j=l.createElement(s,ad({date:t,verboseDate:I?R:void 0,tooltip:o},v),A),F=c||u;return F?l.createElement(F,ad({},f,{verboseDate:I?R:void 0}),j):j}ab.propTypes={date:el().oneOfType([el().instanceOf(Date),el().number]).isRequired,locale:el().string,locales:el().arrayOf(el().string),future:el().bool,timeStyle:af,round:el().string,minTimeLeft:el().number,component:el().elementType.isRequired,tooltip:el().bool.isRequired,formatVerboseDate:el().func,verboseDateFormat:el().object,updateInterval:el().oneOfType([el().number,el().arrayOf(el().shape({threshold:el().number,interval:el().number.isRequired}))]),tick:el().bool,wrapperComponent:el().func,wrapperProps:el().object},ab.defaultProps={locales:[],component:ay,tooltip:!0,verboseDateFormat:{weekday:"long",day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"2-digit",second:"2-digit"},tick:!0},ab=l.memo(ab);let am=ab;var ag,av=31536e9;function ay(e){var t=e.date,n=e.verboseDate,r=e.tooltip,i=e.children,a=ap(e,["date","verboseDate","tooltip","children"]),o=(0,l.useMemo)(function(){return t.toISOString()},[t]);return l.createElement("time",ad({},a,{dateTime:o,title:r?n:void 0}),i)}ay.propTypes={date:el().instanceOf(Date).isRequired,verboseDate:el().string,tooltip:el().bool.isRequired,children:el().string.isRequired};var aw=n(30381),a_=n.n(aw),aE=n(31657);function aS(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function ak(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0?new ru.cA({graphQLErrors:i}):void 0;if(u===s.current.mutationId&&!c.ignoreResults){var f={called:!0,loading:!1,data:r,error:l,client:a};s.current.isMounted&&!(0,ra.D)(s.current.result,f)&&o(s.current.result=f)}var d=e.onCompleted||(null===(n=s.current.options)||void 0===n?void 0:n.onCompleted);return null==d||d(t.data,c),t}).catch(function(t){if(u===s.current.mutationId&&s.current.isMounted){var n,r={loading:!1,error:t,data:void 0,called:!0,client:a};(0,ra.D)(s.current.result,r)||o(s.current.result=r)}var i=e.onError||(null===(n=s.current.options)||void 0===n?void 0:n.onError);if(i)return i(t,c),{data:void 0,errors:t};throw t})},[]),c=(0,l.useCallback)(function(){s.current.isMounted&&o({called:!1,loading:!1,client:n})},[]);return(0,l.useEffect)(function(){return s.current.isMounted=!0,function(){s.current.isMounted=!1}},[]),[u,(0,n8.pi)({reset:c},a)]}var ou=n(59067),oc=n(28428),ol=n(11186),of=n(78513);function od(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}var oh=function(e){return(0,b.createStyles)({paper:{display:"flex",margin:"".concat(2.5*e.spacing.unit,"px 0"),padding:"".concat(3*e.spacing.unit,"px ").concat(3.5*e.spacing.unit,"px")},content:{flex:1,width:"100%"},actions:od({marginTop:-(1.5*e.spacing.unit),marginLeft:-(4*e.spacing.unit)},e.breakpoints.up("sm"),{marginLeft:0,marginRight:-(1.5*e.spacing.unit)}),itemBlock:{border:"1px solid rgba(224, 224, 224, 1)",borderRadius:e.shape.borderRadius,padding:2*e.spacing.unit,marginTop:e.spacing.unit},itemBlockText:{overflowWrap:"anywhere"}})},op=(0,b.withStyles)(oh)(function(e){var t=e.actions,n=e.children,r=e.classes;return l.createElement(ia.default,{className:r.paper},l.createElement("div",{className:r.content},n),t&&l.createElement("div",{className:r.actions},t))}),ob=function(e){var t=e.title;return l.createElement(x.default,{variant:"subtitle2",gutterBottom:!0},t)},om=function(e){var t=e.children,n=e.value;return l.createElement(x.default,{variant:"body1",noWrap:!0},t||n)},og=(0,b.withStyles)(oh)(function(e){var t=e.children,n=e.classes,r=e.value;return l.createElement("div",{className:n.itemBlock},l.createElement(x.default,{variant:"body1",className:n.itemBlockText},t||r))});function ov(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]-1}let sZ=sq;function sX(e,t){var n=this.__data__,r=s$(n,e);return r<0?(++this.size,n.push([e,t])):n[r][1]=t,this}let sJ=sX;function sQ(e){var t=-1,n=null==e?0:e.length;for(this.clear();++t-1&&e%1==0&&e-1&&e%1==0&&e<=cI}let cN=cD;var cP="[object Arguments]",cR="[object Array]",cj="[object Boolean]",cF="[object Date]",cY="[object Error]",cB="[object Function]",cU="[object Map]",cH="[object Number]",c$="[object Object]",cz="[object RegExp]",cG="[object Set]",cW="[object String]",cK="[object WeakMap]",cV="[object ArrayBuffer]",cq="[object DataView]",cZ="[object Float64Array]",cX="[object Int8Array]",cJ="[object Int16Array]",cQ="[object Int32Array]",c1="[object Uint8Array]",c0="[object Uint8ClampedArray]",c2="[object Uint16Array]",c3="[object Uint32Array]",c4={};function c5(e){return eD(e)&&cN(e.length)&&!!c4[eC(e)]}c4["[object Float32Array]"]=c4[cZ]=c4[cX]=c4[cJ]=c4[cQ]=c4[c1]=c4[c0]=c4[c2]=c4[c3]=!0,c4[cP]=c4[cR]=c4[cV]=c4[cj]=c4[cq]=c4[cF]=c4[cY]=c4[cB]=c4[cU]=c4[cH]=c4[c$]=c4[cz]=c4[cG]=c4[cW]=c4[cK]=!1;let c6=c5;function c9(e){return function(t){return e(t)}}let c8=c9;var c7=n(79730),le=c7.Z&&c7.Z.isTypedArray,lt=le?c8(le):c6;let ln=lt;var lr=Object.prototype.hasOwnProperty;function li(e,t){var n=cT(e),r=!n&&ck(e),i=!n&&!r&&(0,cM.Z)(e),a=!n&&!r&&!i&&ln(e),o=n||r||i||a,s=o?cm(e.length,String):[],u=s.length;for(var c in e)(t||lr.call(e,c))&&!(o&&("length"==c||i&&("offset"==c||"parent"==c)||a&&("buffer"==c||"byteLength"==c||"byteOffset"==c)||cC(c,u)))&&s.push(c);return s}let la=li;var lo=Object.prototype;function ls(e){var t=e&&e.constructor;return e===("function"==typeof t&&t.prototype||lo)}let lu=ls;var lc=sM(Object.keys,Object);let ll=lc;var lf=Object.prototype.hasOwnProperty;function ld(e){if(!lu(e))return ll(e);var t=[];for(var n in Object(e))lf.call(e,n)&&"constructor"!=n&&t.push(n);return t}let lh=ld;function lp(e){return null!=e&&cN(e.length)&&!ui(e)}let lb=lp;function lm(e){return lb(e)?la(e):lh(e)}let lg=lm;function lv(e,t){return e&&cp(t,lg(t),e)}let ly=lv;function lw(e){var t=[];if(null!=e)for(var n in Object(e))t.push(n);return t}let l_=lw;var lE=Object.prototype.hasOwnProperty;function lS(e){if(!ed(e))return l_(e);var t=lu(e),n=[];for(var r in e)"constructor"==r&&(t||!lE.call(e,r))||n.push(r);return n}let lk=lS;function lx(e){return lb(e)?la(e,!0):lk(e)}let lT=lx;function lM(e,t){return e&&cp(t,lT(t),e)}let lO=lM;var lA=n(42896);function lL(e,t){var n=-1,r=e.length;for(t||(t=Array(r));++n=0||(i[n]=e[n]);return i}function hc(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}var hl=function(e){return Array.isArray(e)&&0===e.length},hf=function(e){return"function"==typeof e},hd=function(e){return null!==e&&"object"==typeof e},hh=function(e){return String(Math.floor(Number(e)))===e},hp=function(e){return"[object String]"===Object.prototype.toString.call(e)},hb=function(e){return 0===l.Children.count(e)},hm=function(e){return hd(e)&&hf(e.then)};function hg(e,t,n,r){void 0===r&&(r=0);for(var i=d8(t);e&&r=0?[]:{}}}return(0===a?e:i)[o[a]]===n?e:(void 0===n?delete i[o[a]]:i[o[a]]=n,0===a&&void 0===n&&delete r[o[a]],r)}function hy(e,t,n,r){void 0===n&&(n=new WeakMap),void 0===r&&(r={});for(var i=0,a=Object.keys(e);i0?t.map(function(t){return x(t,hg(e,t))}):[Promise.resolve("DO_NOT_DELETE_YOU_WILL_BE_FIRED")]).then(function(e){return e.reduce(function(e,n,r){return"DO_NOT_DELETE_YOU_WILL_BE_FIRED"===n||n&&(e=hv(e,t[r],n)),e},{})})},[x]),M=(0,l.useCallback)(function(e){return Promise.all([T(e),h.validationSchema?k(e):{},h.validate?S(e):{}]).then(function(e){var t=e[0],n=e[1],r=e[2];return sx.all([t,n,r],{arrayMerge:hC})})},[h.validate,h.validationSchema,T,S,k]),O=hP(function(e){return void 0===e&&(e=_.values),E({type:"SET_ISVALIDATING",payload:!0}),M(e).then(function(e){return v.current&&(E({type:"SET_ISVALIDATING",payload:!1}),sh()(_.errors,e)||E({type:"SET_ERRORS",payload:e})),e})});(0,l.useEffect)(function(){o&&!0===v.current&&sh()(p.current,h.initialValues)&&O(p.current)},[o,O]);var A=(0,l.useCallback)(function(e){var t=e&&e.values?e.values:p.current,n=e&&e.errors?e.errors:b.current?b.current:h.initialErrors||{},r=e&&e.touched?e.touched:m.current?m.current:h.initialTouched||{},i=e&&e.status?e.status:g.current?g.current:h.initialStatus;p.current=t,b.current=n,m.current=r,g.current=i;var a=function(){E({type:"RESET_FORM",payload:{isSubmitting:!!e&&!!e.isSubmitting,errors:n,touched:r,status:i,values:t,isValidating:!!e&&!!e.isValidating,submitCount:e&&e.submitCount&&"number"==typeof e.submitCount?e.submitCount:0}})};if(h.onReset){var o=h.onReset(_.values,V);hm(o)?o.then(a):a()}else a()},[h.initialErrors,h.initialStatus,h.initialTouched]);(0,l.useEffect)(function(){!0===v.current&&!sh()(p.current,h.initialValues)&&(c&&(p.current=h.initialValues,A()),o&&O(p.current))},[c,h.initialValues,A,o,O]),(0,l.useEffect)(function(){c&&!0===v.current&&!sh()(b.current,h.initialErrors)&&(b.current=h.initialErrors||hk,E({type:"SET_ERRORS",payload:h.initialErrors||hk}))},[c,h.initialErrors]),(0,l.useEffect)(function(){c&&!0===v.current&&!sh()(m.current,h.initialTouched)&&(m.current=h.initialTouched||hx,E({type:"SET_TOUCHED",payload:h.initialTouched||hx}))},[c,h.initialTouched]),(0,l.useEffect)(function(){c&&!0===v.current&&!sh()(g.current,h.initialStatus)&&(g.current=h.initialStatus,E({type:"SET_STATUS",payload:h.initialStatus}))},[c,h.initialStatus,h.initialTouched]);var L=hP(function(e){if(y.current[e]&&hf(y.current[e].validate)){var t=hg(_.values,e),n=y.current[e].validate(t);return hm(n)?(E({type:"SET_ISVALIDATING",payload:!0}),n.then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}}),E({type:"SET_ISVALIDATING",payload:!1})})):(E({type:"SET_FIELD_ERROR",payload:{field:e,value:n}}),Promise.resolve(n))}return h.validationSchema?(E({type:"SET_ISVALIDATING",payload:!0}),k(_.values,e).then(function(e){return e}).then(function(t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t[e]}}),E({type:"SET_ISVALIDATING",payload:!1})})):Promise.resolve()}),C=(0,l.useCallback)(function(e,t){var n=t.validate;y.current[e]={validate:n}},[]),I=(0,l.useCallback)(function(e){delete y.current[e]},[]),D=hP(function(e,t){return E({type:"SET_TOUCHED",payload:e}),(void 0===t?i:t)?O(_.values):Promise.resolve()}),N=(0,l.useCallback)(function(e){E({type:"SET_ERRORS",payload:e})},[]),P=hP(function(e,t){var r=hf(e)?e(_.values):e;return E({type:"SET_VALUES",payload:r}),(void 0===t?n:t)?O(r):Promise.resolve()}),R=(0,l.useCallback)(function(e,t){E({type:"SET_FIELD_ERROR",payload:{field:e,value:t}})},[]),j=hP(function(e,t,r){return E({type:"SET_FIELD_VALUE",payload:{field:e,value:t}}),(void 0===r?n:r)?O(hv(_.values,e,t)):Promise.resolve()}),F=(0,l.useCallback)(function(e,t){var n,r=t,i=e;if(!hp(e)){e.persist&&e.persist();var a=e.target?e.target:e.currentTarget,o=a.type,s=a.name,u=a.id,c=a.value,l=a.checked,f=(a.outerHTML,a.options),d=a.multiple;r=t||s||u,i=/number|range/.test(o)?(n=parseFloat(c),isNaN(n)?"":n):/checkbox/.test(o)?hD(hg(_.values,r),l,c):d?hI(f):c}r&&j(r,i)},[j,_.values]),Y=hP(function(e){if(hp(e))return function(t){return F(t,e)};F(e)}),B=hP(function(e,t,n){return void 0===t&&(t=!0),E({type:"SET_FIELD_TOUCHED",payload:{field:e,value:t}}),(void 0===n?i:n)?O(_.values):Promise.resolve()}),U=(0,l.useCallback)(function(e,t){e.persist&&e.persist();var n,r=e.target,i=r.name,a=r.id;r.outerHTML,B(t||i||a,!0)},[B]),H=hP(function(e){if(hp(e))return function(t){return U(t,e)};U(e)}),$=(0,l.useCallback)(function(e){hf(e)?E({type:"SET_FORMIK_STATE",payload:e}):E({type:"SET_FORMIK_STATE",payload:function(){return e}})},[]),z=(0,l.useCallback)(function(e){E({type:"SET_STATUS",payload:e})},[]),G=(0,l.useCallback)(function(e){E({type:"SET_ISSUBMITTING",payload:e})},[]),W=hP(function(){return E({type:"SUBMIT_ATTEMPT"}),O().then(function(e){var t,n=e instanceof Error;if(!n&&0===Object.keys(e).length){try{if(void 0===(t=q()))return}catch(r){throw r}return Promise.resolve(t).then(function(e){return v.current&&E({type:"SUBMIT_SUCCESS"}),e}).catch(function(e){if(v.current)throw E({type:"SUBMIT_FAILURE"}),e})}if(v.current&&(E({type:"SUBMIT_FAILURE"}),n))throw e})}),K=hP(function(e){e&&e.preventDefault&&hf(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hf(e.stopPropagation)&&e.stopPropagation(),W().catch(function(e){console.warn("Warning: An unhandled error was caught from submitForm()",e)})}),V={resetForm:A,validateForm:O,validateField:L,setErrors:N,setFieldError:R,setFieldTouched:B,setFieldValue:j,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,setFormikState:$,submitForm:W},q=hP(function(){return f(_.values,V)}),Z=hP(function(e){e&&e.preventDefault&&hf(e.preventDefault)&&e.preventDefault(),e&&e.stopPropagation&&hf(e.stopPropagation)&&e.stopPropagation(),A()}),X=(0,l.useCallback)(function(e){return{value:hg(_.values,e),error:hg(_.errors,e),touched:!!hg(_.touched,e),initialValue:hg(p.current,e),initialTouched:!!hg(m.current,e),initialError:hg(b.current,e)}},[_.errors,_.touched,_.values]),J=(0,l.useCallback)(function(e){return{setValue:function(t,n){return j(e,t,n)},setTouched:function(t,n){return B(e,t,n)},setError:function(t){return R(e,t)}}},[j,B,R]),Q=(0,l.useCallback)(function(e){var t=hd(e),n=t?e.name:e,r=hg(_.values,n),i={name:n,value:r,onChange:Y,onBlur:H};if(t){var a=e.type,o=e.value,s=e.as,u=e.multiple;"checkbox"===a?void 0===o?i.checked=!!r:(i.checked=!!(Array.isArray(r)&&~r.indexOf(o)),i.value=o):"radio"===a?(i.checked=r===o,i.value=o):"select"===s&&u&&(i.value=i.value||[],i.multiple=!0)}return i},[H,Y,_.values]),ee=(0,l.useMemo)(function(){return!sh()(p.current,_.values)},[p.current,_.values]),et=(0,l.useMemo)(function(){return void 0!==s?ee?_.errors&&0===Object.keys(_.errors).length:!1!==s&&hf(s)?s(h):s:_.errors&&0===Object.keys(_.errors).length},[s,ee,_.errors,h]);return ho({},_,{initialValues:p.current,initialErrors:b.current,initialTouched:m.current,initialStatus:g.current,handleBlur:H,handleChange:Y,handleReset:Z,handleSubmit:K,resetForm:A,setErrors:N,setFormikState:$,setFieldTouched:B,setFieldValue:j,setFieldError:R,setStatus:z,setSubmitting:G,setTouched:D,setValues:P,submitForm:W,validateForm:O,validateField:L,isValid:et,dirty:ee,unregisterField:I,registerField:C,getFieldProps:Q,getFieldMeta:X,getFieldHelpers:J,validateOnBlur:i,validateOnChange:n,validateOnMount:o})}function hM(e){var t=hT(e),n=e.component,r=e.children,i=e.render,a=e.innerRef;return(0,l.useImperativeHandle)(a,function(){return t}),(0,l.createElement)(h_,{value:t},n?(0,l.createElement)(n,t):i?i(t):r?hf(r)?r(t):hb(r)?null:l.Children.only(r):null)}function hO(e){var t={};if(e.inner){if(0===e.inner.length)return hv(t,e.path,e.message);for(var n=e.inner,r=Array.isArray(n),i=0,n=r?n:n[Symbol.iterator]();;){if(r){if(i>=n.length)break;a=n[i++]}else{if((i=n.next()).done)break;a=i.value}var a,o=a;hg(t,o.path)||(t=hv(t,o.path,o.message))}}return t}function hA(e,t,n,r){void 0===n&&(n=!1),void 0===r&&(r={});var i=hL(e);return t[n?"validateSync":"validate"](i,{abortEarly:!1,context:r})}function hL(e){var t=Array.isArray(e)?[]:{};for(var n in e)if(Object.prototype.hasOwnProperty.call(e,n)){var r=String(n);!0===Array.isArray(e[r])?t[r]=e[r].map(function(e){return!0===Array.isArray(e)||sj(e)?hL(e):""!==e?e:void 0}):sj(e[r])?t[r]=hL(e[r]):t[r]=""!==e[r]?e[r]:void 0}return t}function hC(e,t,n){var r=e.slice();return t.forEach(function(t,i){if(void 0===r[i]){var a=!1!==n.clone&&n.isMergeableObject(t);r[i]=a?sx(Array.isArray(t)?[]:{},t,n):t}else n.isMergeableObject(t)?r[i]=sx(e[i],t,n):-1===e.indexOf(t)&&r.push(t)}),r}function hI(e){return Array.from(e).filter(function(e){return e.selected}).map(function(e){return e.value})}function hD(e,t,n){if("boolean"==typeof e)return Boolean(t);var r=[],i=!1,a=-1;if(Array.isArray(e))r=e,i=(a=e.indexOf(n))>=0;else if(!n||"true"==n||"false"==n)return Boolean(t);return t&&n&&!i?r.concat(n):i?r.slice(0,a).concat(r.slice(a+1)):r}var hN="undefined"!=typeof window&&void 0!==window.document&&void 0!==window.document.createElement?l.useLayoutEffect:l.useEffect;function hP(e){var t=(0,l.useRef)(e);return hN(function(){t.current=e}),(0,l.useCallback)(function(){for(var e=arguments.length,n=Array(e),r=0;re?t:e},0);return Array.from(ho({},e,{length:t+1}))};(function(e){function t(t){var n;return(n=e.call(this,t)||this).updateArrayField=function(e,t,r){var i=n.props,a=i.name;(0,i.formik.setFormikState)(function(n){var i="function"==typeof r?r:e,o="function"==typeof t?t:e,s=hv(n.values,a,e(hg(n.values,a))),u=r?i(hg(n.errors,a)):void 0,c=t?o(hg(n.touched,a)):void 0;return hl(u)&&(u=void 0),hl(c)&&(c=void 0),ho({},n,{values:s,errors:r?hv(n.errors,a,u):n.errors,touched:t?hv(n.touched,a,c):n.touched})})},n.push=function(e){return n.updateArrayField(function(t){return[].concat(hH(t),[ha(e)])},!1,!1)},n.handlePush=function(e){return function(){return n.push(e)}},n.swap=function(e,t){return n.updateArrayField(function(n){return hY(n,e,t)},!0,!0)},n.handleSwap=function(e,t){return function(){return n.swap(e,t)}},n.move=function(e,t){return n.updateArrayField(function(n){return hF(n,e,t)},!0,!0)},n.handleMove=function(e,t){return function(){return n.move(e,t)}},n.insert=function(e,t){return n.updateArrayField(function(n){return hB(n,e,t)},function(t){return hB(t,e,null)},function(t){return hB(t,e,null)})},n.handleInsert=function(e,t){return function(){return n.insert(e,t)}},n.replace=function(e,t){return n.updateArrayField(function(n){return hU(n,e,t)},!1,!1)},n.handleReplace=function(e,t){return function(){return n.replace(e,t)}},n.unshift=function(e){var t=-1;return n.updateArrayField(function(n){var r=n?[e].concat(n):[e];return t<0&&(t=r.length),r},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n},function(e){var n=e?[null].concat(e):[null];return t<0&&(t=n.length),n}),t},n.handleUnshift=function(e){return function(){return n.unshift(e)}},n.handleRemove=function(e){return function(){return n.remove(e)}},n.handlePop=function(){return function(){return n.pop()}},n.remove=n.remove.bind(hc(n)),n.pop=n.pop.bind(hc(n)),n}hs(t,e);var n=t.prototype;return n.componentDidUpdate=function(e){this.props.validateOnChange&&this.props.formik.validateOnChange&&!sh()(hg(e.formik.values,e.name),hg(this.props.formik.values,this.props.name))&&this.props.formik.validateForm(this.props.formik.values)},n.remove=function(e){var t;return this.updateArrayField(function(n){var r=n?hH(n):[];return t||(t=r[e]),hf(r.splice)&&r.splice(e,1),r},!0,!0),t},n.pop=function(){var e;return this.updateArrayField(function(t){var n=t;return e||(e=n&&n.pop&&n.pop()),n},!0,!0),e},n.render=function(){var e={push:this.push,pop:this.pop,swap:this.swap,move:this.move,insert:this.insert,replace:this.replace,unshift:this.unshift,remove:this.remove,handlePush:this.handlePush,handlePop:this.handlePop,handleSwap:this.handleSwap,handleMove:this.handleMove,handleInsert:this.handleInsert,handleReplace:this.handleReplace,handleUnshift:this.handleUnshift,handleRemove:this.handleRemove},t=this.props,n=t.component,r=t.render,i=t.children,a=t.name,o=hu(t.formik,["validate","validationSchema"]),s=ho({},e,{form:o,name:a});return n?(0,l.createElement)(n,s):r?r(s):i?"function"==typeof i?i(s):hb(i)?null:l.Children.only(i):null},t})(l.Component).defaultProps={validateOnChange:!0},l.Component,l.Component;var h$=n(24802),hz=n(71209),hG=n(91750),hW=n(11970),hK=n(4689),hV=n(67598),hq=function(){return(hq=Object.assign||function(e){for(var t,n=1,r=arguments.length;nt.indexOf(r)&&(n[r]=e[r]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols)for(var i=0,r=Object.getOwnPropertySymbols(e);it.indexOf(r[i])&&(n[r[i]]=e[r[i]]);return n}function hX(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hZ(n,["onBlur"]),a=e.form,o=a.isSubmitting,s=a.touched,u=a.errors,c=e.onBlur,l=e.helperText,f=hZ(e,["disabled","field","form","onBlur","helperText"]),d=hg(u,i.name),h=hg(s,i.name)&&!!d;return hq(hq({variant:f.variant,error:h,helperText:h?d:l,disabled:null!=t?t:o,onBlur:null!=c?c:function(e){r(null!=e?e:i.name)}},i),f)}function hJ(e){var t=e.children,n=hZ(e,["children"]);return(0,l.createElement)(i_.Z,hq({},hX(n)),t)}function hQ(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hZ(n,["onBlur"]),a=e.form.isSubmitting,o=(e.type,e.onBlur),s=hZ(e,["disabled","field","form","type","onBlur"]);return hq(hq({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h1(e){return(0,l.createElement)(h$.Z,hq({},hQ(e)))}function h0(e){var t,n=e.disabled,r=e.field,i=r.onBlur,a=hZ(r,["onBlur"]),o=e.form.isSubmitting,s=(e.type,e.onBlur),u=hZ(e,["disabled","field","form","type","onBlur"]);return hq(hq({disabled:null!=n?n:o,indeterminate:!Array.isArray(a.value)&&null==a.value,onBlur:null!=s?s:function(e){i(null!=e?e:a.name)}},a),u)}function h2(e){return(0,l.createElement)(hz.Z,hq({},h0(e)))}function h3(e){var t=e.Label,n=hZ(e,["Label"]);return(0,l.createElement)(hG.Z,hq({control:(0,l.createElement)(hz.Z,hq({},h0(n)))},t))}function h4(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hZ(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hZ(e,["disabled","field","form","onBlur"]);return hq(hq({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h5(e){return(0,l.createElement)(hW.default,hq({},h4(e)))}function h6(e){var t=e.field,n=t.onBlur,r=hZ(t,["onBlur"]),i=(e.form,e.onBlur),a=hZ(e,["field","form","onBlur"]);return hq(hq({onBlur:null!=i?i:function(e){n(null!=e?e:r.name)}},r),a)}function h9(e){return(0,l.createElement)(hK.Z,hq({},h6(e)))}function h8(e){var t=e.disabled,n=e.field,r=n.onBlur,i=hZ(n,["onBlur"]),a=e.form.isSubmitting,o=e.onBlur,s=hZ(e,["disabled","field","form","onBlur"]);return hq(hq({disabled:null!=t?t:a,onBlur:null!=o?o:function(e){r(null!=e?e:i.name)}},i),s)}function h7(e){return(0,l.createElement)(hV.default,hq({},h8(e)))}hJ.displayName="FormikMaterialUITextField",h1.displayName="FormikMaterialUISwitch",h2.displayName="FormikMaterialUICheckbox",h3.displayName="FormikMaterialUICheckboxWithLabel",h5.displayName="FormikMaterialUISelect",h9.displayName="FormikMaterialUIRadioGroup",h7.displayName="FormikMaterialUIInputBase";try{a=Map}catch(pe){}try{o=Set}catch(pt){}function pn(e,t,n){if(!e||"object"!=typeof e||"function"==typeof e)return e;if(e.nodeType&&"cloneNode"in e)return e.cloneNode(!0);if(e instanceof Date)return new Date(e.getTime());if(e instanceof RegExp)return RegExp(e);if(Array.isArray(e))return e.map(pr);if(a&&e instanceof a)return new Map(Array.from(e.entries()));if(o&&e instanceof o)return new Set(Array.from(e.values()));if(e instanceof Object){t.push(e);var r=Object.create(e);for(var i in n.push(r),e){var s=t.findIndex(function(t){return t===e[i]});r[i]=s>-1?n[s]:pn(e[i],t,n)}return r}return e}function pr(e){return pn(e,[],[])}let pi=Object.prototype.toString,pa=Error.prototype.toString,po=RegExp.prototype.toString,ps="undefined"!=typeof Symbol?Symbol.prototype.toString:()=>"",pu=/^Symbol\((.*)\)(.*)$/;function pc(e){if(e!=+e)return"NaN";let t=0===e&&1/e<0;return t?"-0":""+e}function pl(e,t=!1){if(null==e||!0===e||!1===e)return""+e;let n=typeof e;if("number"===n)return pc(e);if("string"===n)return t?`"${e}"`:e;if("function"===n)return"[Function "+(e.name||"anonymous")+"]";if("symbol"===n)return ps.call(e).replace(pu,"Symbol($1)");let r=pi.call(e).slice(8,-1);return"Date"===r?isNaN(e.getTime())?""+e:e.toISOString(e):"Error"===r||e instanceof Error?"["+pa.call(e)+"]":"RegExp"===r?po.call(e):null}function pf(e,t){let n=pl(e,t);return null!==n?n:JSON.stringify(e,function(e,n){let r=pl(this[e],t);return null!==r?r:n},2)}let pd={default:"${path} is invalid",required:"${path} is a required field",oneOf:"${path} must be one of the following values: ${values}",notOneOf:"${path} must not be one of the following values: ${values}",notType({path:e,type:t,value:n,originalValue:r}){let i=null!=r&&r!==n,a=`${e} must be a \`${t}\` type, but the final value was: \`${pf(n,!0)}\``+(i?` (cast from the value \`${pf(r,!0)}\`).`:".");return null===n&&(a+='\n If "null" is intended as an empty value be sure to mark the schema as `.nullable()`'),a},defined:"${path} must be defined"},ph={length:"${path} must be exactly ${length} characters",min:"${path} must be at least ${min} characters",max:"${path} must be at most ${max} characters",matches:'${path} must match the following: "${regex}"',email:"${path} must be a valid email",url:"${path} must be a valid URL",uuid:"${path} must be a valid UUID",trim:"${path} must be a trimmed string",lowercase:"${path} must be a lowercase string",uppercase:"${path} must be a upper case string"},pp={min:"${path} must be greater than or equal to ${min}",max:"${path} must be less than or equal to ${max}",lessThan:"${path} must be less than ${less}",moreThan:"${path} must be greater than ${more}",positive:"${path} must be a positive number",negative:"${path} must be a negative number",integer:"${path} must be an integer"},pb={min:"${path} field must be later than ${min}",max:"${path} field must be at earlier than ${max}"},pm={isValue:"${path} field must be ${value}"},pg={noUnknown:"${path} field has unspecified keys: ${unknown}"},pv={min:"${path} field must have at least ${min} items",max:"${path} field must have less than or equal to ${max} items",length:"${path} must be have ${length} items"};Object.assign(Object.create(null),{mixed:pd,string:ph,number:pp,date:pb,object:pg,array:pv,boolean:pm});var py=n(18721),pw=n.n(py);let p_=e=>e&&e.__isYupSchema__;class pE{constructor(e,t){if(this.refs=e,this.refs=e,"function"==typeof t){this.fn=t;return}if(!pw()(t,"is"))throw TypeError("`is:` is required for `when()` conditions");if(!t.then&&!t.otherwise)throw TypeError("either `then:` or `otherwise:` is required for `when()` conditions");let{is:n,then:r,otherwise:i}=t,a="function"==typeof n?n:(...e)=>e.every(e=>e===n);this.fn=function(...e){let t=e.pop(),n=e.pop(),o=a(...e)?r:i;if(o)return"function"==typeof o?o(n):n.concat(o.resolve(t))}}resolve(e,t){let n=this.refs.map(e=>e.getValue(null==t?void 0:t.value,null==t?void 0:t.parent,null==t?void 0:t.context)),r=this.fn.apply(e,n.concat(e,t));if(void 0===r||r===e)return e;if(!p_(r))throw TypeError("conditions must return a schema object");return r.resolve(t)}}let pS=pE;function pk(e){return null==e?[]:[].concat(e)}function px(){return(px=Object.assign||function(e){for(var t=1;tpf(t[n])):"function"==typeof e?e(t):e}static isError(e){return e&&"ValidationError"===e.name}constructor(e,t,n,r){super(),this.name="ValidationError",this.value=t,this.path=n,this.type=r,this.errors=[],this.inner=[],pk(e).forEach(e=>{pM.isError(e)?(this.errors.push(...e.errors),this.inner=this.inner.concat(e.inner.length?e.inner:e)):this.errors.push(e)}),this.message=this.errors.length>1?`${this.errors.length} errors occurred`:this.errors[0],Error.captureStackTrace&&Error.captureStackTrace(this,pM)}}let pO=e=>{let t=!1;return(...n)=>{t||(t=!0,e(...n))}};function pA(e,t){let{endEarly:n,tests:r,args:i,value:a,errors:o,sort:s,path:u}=e,c=pO(t),l=r.length,f=[];if(o=o||[],!l)return o.length?c(new pM(o,a,u)):c(null,a);for(let d=0;d=0||(i[n]=e[n]);return i}function pj(e){function t(t,n){let{value:r,path:i="",label:a,options:o,originalValue:s,sync:u}=t,c=pR(t,["value","path","label","options","originalValue","sync"]),{name:l,test:f,params:d,message:h}=e,{parent:p,context:b}=o;function m(e){return pN.isRef(e)?e.getValue(r,p,b):e}function g(e={}){let t=pC()(pP({value:r,originalValue:s,label:a,path:e.path||i},d,e.params),m),n=new pM(pM.formatError(e.message||h,t),r,t.path,e.type||l);return n.params=t,n}let v=pP({path:i,parent:p,type:l,createError:g,resolve:m,options:o,originalValue:s},c);if(!u){try{Promise.resolve(f.call(v,r,v)).then(e=>{pM.isError(e)?n(e):e?n(null,e):n(g())})}catch(y){n(y)}return}let w;try{var _;if(w=f.call(v,r,v),"function"==typeof(null==(_=w)?void 0:_.then))throw Error(`Validation test of type: "${v.type}" returned a Promise during a synchronous validate. This test will finish after the validate call has returned`)}catch(E){n(E);return}pM.isError(w)?n(w):w?n(null,w):n(g())}return t.OPTIONS=e,t}pN.prototype.__isYupRef=!0;let pF=e=>e.substr(0,e.length-1).substr(1);function pY(e,t,n,r=n){let i,a,o;return t?((0,pI.forEach)(t,(s,u,c)=>{let l=u?pF(s):s;if((e=e.resolve({context:r,parent:i,value:n})).innerType){let f=c?parseInt(l,10):0;if(n&&f>=n.length)throw Error(`Yup.reach cannot resolve an array item at index: ${s}, in the path: ${t}. because there is no value at that index. `);i=n,n=n&&n[f],e=e.innerType}if(!c){if(!e.fields||!e.fields[l])throw Error(`The schema does not contain the path: ${t}. (failed at: ${o} which is a type: "${e._type}")`);i=n,n=n&&n[l],e=e.fields[l]}a=l,o=u?"["+s+"]":"."+s}),{schema:e,parent:i,parentPath:a}):{parent:i,parentPath:t,schema:e}}class pB{constructor(){this.list=new Set,this.refs=new Map}get size(){return this.list.size+this.refs.size}describe(){let e=[];for(let t of this.list)e.push(t);for(let[,n]of this.refs)e.push(n.describe());return e}toArray(){return Array.from(this.list).concat(Array.from(this.refs.values()))}add(e){pN.isRef(e)?this.refs.set(e.key,e):this.list.add(e)}delete(e){pN.isRef(e)?this.refs.delete(e.key):this.list.delete(e)}has(e,t){if(this.list.has(e))return!0;let n,r=this.refs.values();for(;!(n=r.next()).done;)if(t(n.value)===e)return!0;return!1}clone(){let e=new pB;return e.list=new Set(this.list),e.refs=new Map(this.refs),e}merge(e,t){let n=this.clone();return e.list.forEach(e=>n.add(e)),e.refs.forEach(e=>n.add(e)),t.list.forEach(e=>n.delete(e)),t.refs.forEach(e=>n.delete(e)),n}}function pU(){return(pU=Object.assign||function(e){for(var t=1;t{this.typeError(pd.notType)}),this.type=(null==e?void 0:e.type)||"mixed",this.spec=pU({strip:!1,strict:!1,abortEarly:!0,recursive:!0,nullable:!1,presence:"optional"},null==e?void 0:e.spec)}get _type(){return this.type}_typeCheck(e){return!0}clone(e){if(this._mutate)return e&&Object.assign(this.spec,e),this;let t=Object.create(Object.getPrototypeOf(this));return t.type=this.type,t._typeError=this._typeError,t._whitelistError=this._whitelistError,t._blacklistError=this._blacklistError,t._whitelist=this._whitelist.clone(),t._blacklist=this._blacklist.clone(),t.exclusiveTests=pU({},this.exclusiveTests),t.deps=[...this.deps],t.conditions=[...this.conditions],t.tests=[...this.tests],t.transforms=[...this.transforms],t.spec=pr(pU({},this.spec,e)),t}label(e){var t=this.clone();return t.spec.label=e,t}meta(...e){if(0===e.length)return this.spec.meta;let t=this.clone();return t.spec.meta=Object.assign(t.spec.meta||{},e[0]),t}withMutation(e){let t=this._mutate;this._mutate=!0;let n=e(this);return this._mutate=t,n}concat(e){if(!e||e===this)return this;if(e.type!==this.type&&"mixed"!==this.type)throw TypeError(`You cannot \`concat()\` schema's of different types: ${this.type} and ${e.type}`);let t=this,n=e.clone(),r=pU({},t.spec,n.spec);return n.spec=r,n._typeError||(n._typeError=t._typeError),n._whitelistError||(n._whitelistError=t._whitelistError),n._blacklistError||(n._blacklistError=t._blacklistError),n._whitelist=t._whitelist.merge(e._whitelist,e._blacklist),n._blacklist=t._blacklist.merge(e._blacklist,e._whitelist),n.tests=t.tests,n.exclusiveTests=t.exclusiveTests,n.withMutation(t=>{e.tests.forEach(e=>{t.test(e.OPTIONS)})}),n}isType(e){return!!this.spec.nullable&&null===e||this._typeCheck(e)}resolve(e){let t=this;if(t.conditions.length){let n=t.conditions;(t=t.clone()).conditions=[],t=(t=n.reduce((t,n)=>n.resolve(t,e),t)).resolve(e)}return t}cast(e,t={}){let n=this.resolve(pU({value:e},t)),r=n._cast(e,t);if(void 0!==e&&!1!==t.assert&&!0!==n.isType(r)){let i=pf(e),a=pf(r);throw TypeError(`The value of ${t.path||"field"} could not be cast to a value that satisfies the schema type: "${n._type}". attempted value: ${i} -`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pU({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pA({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pA({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pU({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pU({},t,{value:e}))._validate(e,pU({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pM.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pM.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pr(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pd.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pd.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pd.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pj(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pk(e).map(e=>new pN(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pS(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pj({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pd.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pj({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pd.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pj({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let p$ of(pH.prototype.__isYupSchema__=!0,["validate","validateSync"]))pH.prototype[`${p$}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pY(this,e,t,n.context);return a[p$](r&&r[i],pU({},n,{parent:r,path:e}))};for(let pz of["equals","is"])pH.prototype[pz]=pH.prototype.oneOf;for(let pG of["not","nope"])pH.prototype[pG]=pH.prototype.notOneOf;pH.prototype.optional=pH.prototype.notRequired;let pW=pH;function pK(){return new pW}pK.prototype=pW.prototype;let pV=e=>null==e;function pq(){return new pZ}class pZ extends pH{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pm.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pV(e)||!0===e})}isFalse(e=pm.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pV(e)||!1===e})}}pq.prototype=pZ.prototype;let pX=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pJ=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pQ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,p1=e=>pV(e)||e===e.trim(),p0=({}).toString();function p2(){return new p3}class p3 extends pH{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p0?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=ph.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pV(t)||t.length===this.resolve(e)}})}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t.length>=this.resolve(e)}})}max(e,t=ph.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pV(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||ph.matches,params:{regex:e},test:t=>pV(t)||""===t&&n||-1!==t.search(e)})}email(e=ph.email){return this.matches(pX,{name:"email",message:e,excludeEmptyString:!0})}url(e=ph.url){return this.matches(pJ,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=ph.uuid){return this.matches(pQ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=ph.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:p1})}lowercase(e=ph.lowercase){return this.transform(e=>pV(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pV(e)||e===e.toLowerCase()})}uppercase(e=ph.uppercase){return this.transform(e=>pV(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pV(e)||e===e.toUpperCase()})}}p2.prototype=p3.prototype;let p4=e=>e!=+e;function p5(){return new p6}class p6 extends pH{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p4(e)}min(e,t=pp.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t>=this.resolve(e)}})}max(e,t=pp.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pV(t)||t<=this.resolve(e)}})}lessThan(e,t=pp.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pV(t)||tthis.resolve(e)}})}positive(e=pp.positive){return this.moreThan(0,e)}negative(e=pp.negative){return this.lessThan(0,e)}integer(e=pp.integer){return this.test({name:"integer",message:e,test:e=>pV(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pV(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pV(t)?t:Math[e](t))}}p5.prototype=p6.prototype;var p9=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p9.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p7=new Date(""),be=e=>"[object Date]"===Object.prototype.toString.call(e);function bt(){return new bn}class bn extends pH{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p7:new Date(e))})})}_typeCheck(e){return be(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pN.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pb.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pV(e)||e>=this.resolve(n)}})}max(e,t=pb.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pV(e)||e<=this.resolve(n)}})}}bn.INVALID_DATE=p7,bt.prototype=bn.prototype,bt.INVALID_DATE=p7;var br=n(11865),bi=n.n(br),ba=n(68929),bo=n.n(ba),bs=n(67523),bu=n.n(bs),bc=n(94633),bl=n.n(bc);function bf(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pI.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(pw()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pN.isRef(o)&&o.isSibling?i(o.path,a):p_(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bl().array(r,n).reverse()}function bd(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bh(e){return(t,n)=>bd(e,t)-bd(e,n)}function bp(){return(bp=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bm(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bg=bh([]);class bv extends pH{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bg,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bb(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bp({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=pw()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pM.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bb(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bp({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pA({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bp({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pH&&i instanceof pH&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bh(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bf(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pI.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return pw()(i,e)&&(a=bp({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pg.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bm(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pg.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bu()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(bo())}snakeCase(){return this.transformKeys(bi())}constantCase(){return this.transformKeys(e=>bi()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pC()(this.fields,e=>e.describe()),e}}function by(e){return new bv(e)}function bw(){return(bw=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,bw({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pM.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pA({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!p_(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pf(e));return t.innerType=e,t}length(e,t=pv.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pV(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pv.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pv.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pV(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}b_.prototype=bE.prototype;var bS=by().shape({name:p2().required("Required"),url:p2().required("Required")}),bk=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hM,{initialValues:t,validationSchema:bS,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hj,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hR,{component:hJ,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hR,{component:hJ,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hR,{component:hJ,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hR,{component:hJ,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ox.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bx=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Edit Bridge",action:l.createElement(aL.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aK.Z,null,l.createElement(bk,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bT(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},ml=n(76023);function mf(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0||(i[n]=e[n]);return i}function mB(e,t){if(null==e)return{};var n,r,i=mY(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mU(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mX={};function mJ(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mX[t]||(mX[t]=mZ(e)),mX[t]}function mQ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mJ(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mV({},e,n[t])},t)}function m1(e){return e.join(" ")}function m0(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m2({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m2(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m0(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mV({},s,{className:m1(m)||void 0,style:mQ(s.className,Object.assign({},s.style,i),n)})}else d=mV({},s,{className:m1(s.className)});var g=h(t.children);return l.createElement(c,mq({key:o},d),g)}}let m3=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m4=/\n/g;function m5(e){return e.match(m4)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m9(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m7(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function ge(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mV({},i,"function"==typeof e?e(t):e)}function gt(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=ge(r,n,i);t.unshift(m7(n,h))}return f&l&&(d.style=mV({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gn(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return gt({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=ge(s,t,o);e.unshift(m7(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m5(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(gt({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=gt({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gc=n(98695),gl=n.n(gc);let gf=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gd=gs(gl(),gu);gd.supportedLanguages=gf;let gh=gd;var gp=n(64566);function gb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gm(){var e=gb(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gm=function(){return e},e}var gg=n0(gm()),gv=function(e){var t=e.children;return l.createElement(ii.Z,null,l.createElement(ie.default,{component:"th",scope:"row",colSpan:3},t))},gy=function(){return l.createElement(gv,null,"...")},gw=function(e){var t=e.children;return l.createElement(gv,null,t)},g_=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gw,null,i);if(t)return l.createElement(gy,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mR.Z,{defaultExpanded:o},l.createElement(mj.Z,{expandIcon:l.createElement(gp.Z,null)},a),l.createElement(mF.Z,{style:s},l.createElement(gh,{language:"toml",style:gu},n))))},gE=function(){var e=ry(gg,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"TOML Configuration"}),l.createElement(g_,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"TOML Configuration"}),l.createElement(g_,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(g_,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gS=n(34823),gk=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gx=(0,b.withStyles)(gk)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gS.N,A.wU);return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r7.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ii.Z,null,l.createElement(ie.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gT=function(){return l.createElement(iv,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(gE,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gx,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mP,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mS,null))))))},gM=function(){return l.createElement(gT,null)},gO=function(){return l.createElement(gM,null)},gA=n(44431),gL=1e18,gC=function(e){return new gA.BigNumber(e).dividedBy(gL).toFixed(8)},gI=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sf.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aK.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ob,{title:"Address"}),l.createElement(om,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ob,{title:"Native Token Balance"}),l.createElement(om,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ob,{title:"LINK Balance"}),l.createElement(om,{value:e.linkBalance?gC(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gU.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,{className:r.footer},l.createElement(aL.Z,{href:"/runs",component:tz},"View More"))))))});function vn(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vr(){var e=vn(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vr=function(){return e},e}var vi=5,va=n0(vr(),g7),vo=function(){var e=ry(va,{variables:{offset:0,limit:vi},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vt,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vi})},vs=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vu=(0,b.withStyles)(vs)(function(e){var t=e.classes,n=(0,A.v9)(gS.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ia.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vc=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vl=(0,b.withStyles)(vc)(function(e){var t=e.classes,n=e.job;return l.createElement(ii.Z,null,l.createElement(ie.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ip,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aA,{tooltip:!0},n.createdAt))))))});function vf(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vd(){var e=vf(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vd=function(){return e},e}var vh=n0(vd()),vp=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vb=(0,b.withStyles)(vp)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r7.Z,null,l.createElement(gz,{visible:o}),l.createElement(gG,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gH,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vl,{job:e,key:t})}))))});function vm(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vg(){var e=vm(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vg=function(){return e},e}var vv=5,vy=n0(vg(),vh),vw=function(){var e=ry(vy,{variables:{offset:0,limit:vv},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vb,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},v_=function(){return l.createElement(iv,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(vo,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gB,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vw,null))))),l.createElement(vu,null))},vE=function(){return l.createElement(v_,null)},vS=function(){return l.createElement(vE,null)},vk=n(87239),vx=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vT=n(5022),vM=n(78718),vO=n.n(vM);function vA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ii.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(ie.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(ie.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aA,{tooltip:!0},e.createdAt))),l.createElement(ie.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yp(t,e.status))},e.status.toLowerCase())))})))}),ym=n(16839),yg=n.n(ym);function yv(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=yg().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yy=n(94164),yw=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},y_=n(73343),yE=n(3379),yS=n.n(yE);function yk(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yy.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:y_.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yw,{data:e}))}))};function yC(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyB&&l.createElement("div",{className:t.runDetails},l.createElement(aL.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yY,{observationSource:n.observationSource})))});function y$(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vT.parse(e),!0}catch(t){return!1}})}),wK=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hM,{initialValues:t,validationSchema:wW,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hj,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hR,{component:hJ,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ox.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wV=n(50109),wq="persistSpec";function wZ(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wV.t8(wq,n),{toml:n}):{toml:wV.U2(wq)||""}}var wX=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wZ({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wV.t8("".concat(wq),t),n&&n(t)};return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"New Job"}),l.createElement(aK.Z,null,l.createElement(wK,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wJ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _O(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(_K,e)},_q=function(){var e=_V({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_H,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_Z=function(e){var t=e.csaKey;return l.createElement(ii.Z,{hover:!0},l.createElement(ie.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_T,{data:t.publicKey}))))};function _X(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _J(){var e=_X(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _J=function(){return e},e}var _Q=n0(_J()),_1=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r9.Z,null,l.createElement(sf.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ox.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(it.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,null,"Public Key"))),l.createElement(r7.Z,null,l.createElement(gz,{visible:o}),l.createElement(gG,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gH,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_Z,{csaKey:e,key:t})}))))};function _0(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(EO,e)};function EL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(EQ,e)},E4=function(){return os(E1)},E5=function(){return os(E0)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return ry(E2,e)};function E9(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(SV,e)};function SZ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kq(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kZ=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kV(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kK(kG({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r9.Z,null,l.createElement(aK.Z,null,l.createElement(k$,{object:n})))};function kX(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kJ(e){for(var t=1;t0&&l.createElement(ki,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kZ,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kP,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k9(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k9(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k7=n0(k8(),k5),xe=function(){var e=ry(k7,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(ij,null);if(r)return l.createElement(iN,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oo,null);default:return null}};function xt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xn(){var e=xt(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xn=function(){return e},e}var xr=n0(xn()),xi=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iw,null,"Job Runs")),t&&l.createElement(ij,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(yb,{runs:o}),l.createElement(ir.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xa(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xo(){var e=xa(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xo=function(){return e},e}var xs=n0(xo(),xr),xu=function(){var e=iF(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=ry(xs,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iN,{error:o}):l.createElement(xi,{loading:a,data:i,page:t,pageSize:n})},xc=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xu,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(xe,null)))},xl=by().shape({name:p2().required("Required"),uri:p2().required("Required"),publicKey:p2().required("Required")}),xf=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hM,{initialValues:t,validationSchema:xl,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hj,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ox.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xd=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Edit Feeds Manager"}),l.createElement(aK.Z,null,l.createElement(xf,{initialValues:r,onSubmit:n})))))};function xh(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xp(){var e=xh(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xp=function(){return e},e}var xb=n0(xp()),xm=function(){return ry(xb)};function xg(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(xZ,e)};function xJ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TH,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},Tz={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TG=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Register Feeds Manager"}),l.createElement(aK.Z,null,l.createElement(xf,{initialValues:Tz,onSubmit:t})))))};function TW(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return Mp(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mR.Z,{defaultExpanded:0===n,key:n},l.createElement(mj.Z,{expandIcon:l.createElement(gp.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Eu.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aA,{tooltip:!0},e.createdAt)))),l.createElement(mF.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ox.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gh,{language:"toml",style:gu,"data-testid":"codeblock"},e.definition)))}),l.createElement(oI,{open:null!=c,title:c?My[c.action].title:"",body:c?My[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Mi,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M_(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ME(){var e=M_(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return ME=function(){return e},e}var MS=n0(ME(),Mg),Mk=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iw,null,"Job Proposal #",a.id))),l.createElement(T8,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(TU,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(Mw,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Mx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(55977),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(55977),a=n(47886),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(97779),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(55977),a=n(15857),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ri,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nr})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;nr,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(23564);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(23564),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},87462(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;tr})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(55977),p=__webpack_require__(15857),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t5(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t9("(",t5(e.variableDefinitions,", "),")"),i=t5(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t5([t,t5([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t9(" = ",r)+t9(" ",t5(i," "))},SelectionSet:function(e){return t6(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t9("",t,": ")+n,s=o+t9("(",t5(r,", "),")");return s.length>t2&&(s=o+t9("(\n",t8(t5(r,"\n")),"\n)")),t5([s,t5(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t9(" ",t5(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t5(["...",t9("on ",t),t5(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t9("(",t5(r,", "),")")," ")+"on ".concat(n," ").concat(t9("",t5(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t5(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t5(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t9("(",t5(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t5(["schema",t5(t," "),t6(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t5(["scalar",e.name,t5(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["type",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t9("(\n",t8(t5(n,"\n")),"\n)"):t9("(",t5(n,", "),")"))+": "+r+t9(" ",t5(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t5([t+": "+n,t9("= ",r),t5(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["interface",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t5(["union",t,t5(n," "),r&&0!==r.length?"= "+t5(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t5(["enum",t,t5(n," "),t6(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t5([e.name,t5(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t5(["input",t,t5(n," "),t6(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t9("(\n",t8(t5(n,"\n")),"\n)"):t9("(",t5(n,", "),")"))+(r?" repeatable":"")+" on "+t5(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t5(["extend schema",t5(t," "),t6(n)]," ")},ScalarTypeExtension:function(e){var t;return t5(["extend scalar",e.name,t5(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["extend type",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["extend interface",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t5(["extend union",t,t5(n," "),r&&0!==r.length?"= "+t5(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t5(["extend enum",t,t5(n," "),t6(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t5(["extend input",t,t5(n," "),t6(r)]," ")}};function t4(e){return function(t){return t5([t.description,e(t)],"\n")}}function t5(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t6(e){return t9("{\n",t8(t5(e,"\n")),"\n}")}function t9(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t8(e){return t9(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n5(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n6(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n9(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n8(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e9(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n8(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n8(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r5=new(t_.mr?WeakMap:Map);function r6(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r5.set(e,(r5.get(e)+1)%1e15),n.apply(this,arguments)})}function r9(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r8=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r5.has(n)||(r5.set(n,0),r6(n,"evict"),r6(n,"modify"),r6(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r9(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r9(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r5.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r5.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e8(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r8(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r8&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n6(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r8(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e8(e5(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e9(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e8(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i6(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i9(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i8(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i6(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i5=[];function i6(e,t){var n=e.map;return n.has(t)||n.set(t,i5.pop()||{map:new Map}),n.get(t)}function i9(e,t){if(e===t||!t||i8(t))return e;if(!e||i8(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i9(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i9(t.map.get(n),e.map.get(n)))})}return a}function i8(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i8(r)&&(i5.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","VRFSpec","WebhookSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file +`+(a!==i?`result of cast: ${a}`:""))}return r}_cast(e,t){let n=void 0===e?e:this.transforms.reduce((t,n)=>n.call(this,t,e,this),e);return void 0===n&&(n=this.getDefault()),n}_validate(e,t={},n){let{sync:r,path:i,from:a=[],originalValue:o=e,strict:s=this.spec.strict,abortEarly:u=this.spec.abortEarly}=t,c=e;s||(c=this._cast(c,pU({assert:!1},t)));let l={value:c,path:i,options:t,originalValue:o,schema:this,label:this.spec.label,sync:r,from:a},f=[];this._typeError&&f.push(this._typeError),this._whitelistError&&f.push(this._whitelistError),this._blacklistError&&f.push(this._blacklistError),pA({args:l,value:c,path:i,sync:r,tests:f,endEarly:u},e=>{if(e)return void n(e,c);pA({tests:this.tests,args:l,path:i,sync:r,value:c,endEarly:u},n)})}validate(e,t,n){let r=this.resolve(pU({},t,{value:e}));return"function"==typeof n?r._validate(e,t,n):new Promise((n,i)=>r._validate(e,t,(e,t)=>{e?i(e):n(t)}))}validateSync(e,t){let n;return this.resolve(pU({},t,{value:e}))._validate(e,pU({},t,{sync:!0}),(e,t)=>{if(e)throw e;n=t}),n}isValid(e,t){return this.validate(e,t).then(()=>!0,e=>{if(pM.isError(e))return!1;throw e})}isValidSync(e,t){try{return this.validateSync(e,t),!0}catch(n){if(pM.isError(n))return!1;throw n}}_getDefault(){let e=this.spec.default;return null==e?e:"function"==typeof e?e.call(this):pr(e)}getDefault(e){return this.resolve(e||{})._getDefault()}default(e){return 0===arguments.length?this._getDefault():this.clone({default:e})}strict(e=!0){var t=this.clone();return t.spec.strict=e,t}_isPresent(e){return null!=e}defined(e=pd.defined){return this.test({message:e,name:"defined",exclusive:!0,test:e=>void 0!==e})}required(e=pd.required){return this.clone({presence:"required"}).withMutation(t=>t.test({message:e,name:"required",exclusive:!0,test(e){return this.schema._isPresent(e)}}))}notRequired(){var e=this.clone({presence:"optional"});return e.tests=e.tests.filter(e=>"required"!==e.OPTIONS.name),e}nullable(e=!0){return this.clone({nullable:!1!==e})}transform(e){var t=this.clone();return t.transforms.push(e),t}test(...e){let t;if(void 0===(t=1===e.length?"function"==typeof e[0]?{test:e[0]}:e[0]:2===e.length?{name:e[0],test:e[1]}:{name:e[0],message:e[1],test:e[2]}).message&&(t.message=pd.default),"function"!=typeof t.test)throw TypeError("`test` is a required parameters");let n=this.clone(),r=pj(t),i=t.exclusive||t.name&&!0===n.exclusiveTests[t.name];if(t.exclusive&&!t.name)throw TypeError("Exclusive tests must provide a unique `name` identifying the test");return t.name&&(n.exclusiveTests[t.name]=!!t.exclusive),n.tests=n.tests.filter(e=>e.OPTIONS.name!==t.name||!i&&e.OPTIONS.test!==r.OPTIONS.test),n.tests.push(r),n}when(e,t){Array.isArray(e)||"string"==typeof e||(t=e,e=".");let n=this.clone(),r=pk(e).map(e=>new pN(e));return r.forEach(e=>{e.isSibling&&n.deps.push(e.key)}),n.conditions.push(new pS(r,t)),n}typeError(e){var t=this.clone();return t._typeError=pj({message:e,name:"typeError",test(e){return!!(void 0===e||this.schema.isType(e))||this.createError({params:{type:this.schema._type}})}}),t}oneOf(e,t=pd.oneOf){var n=this.clone();return e.forEach(e=>{n._whitelist.add(e),n._blacklist.delete(e)}),n._whitelistError=pj({message:t,name:"oneOf",test(e){if(void 0===e)return!0;let t=this.schema._whitelist;return!!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}notOneOf(e,t=pd.notOneOf){var n=this.clone();return e.forEach(e=>{n._blacklist.add(e),n._whitelist.delete(e)}),n._blacklistError=pj({message:t,name:"notOneOf",test(e){let t=this.schema._blacklist;return!t.has(e,this.resolve)||this.createError({params:{values:t.toArray().join(", ")}})}}),n}strip(e=!0){let t=this.clone();return t.spec.strip=e,t}describe(){let e=this.clone(),{label:t,meta:n}=e.spec,r={meta:n,label:t,type:e.type,oneOf:e._whitelist.describe(),notOneOf:e._blacklist.describe(),tests:e.tests.map(e=>({name:e.OPTIONS.name,params:e.OPTIONS.params})).filter((e,t,n)=>n.findIndex(t=>t.name===e.name)===t)};return r}}for(let p$ of(pH.prototype.__isYupSchema__=!0,["validate","validateSync"]))pH.prototype[`${p$}At`]=function(e,t,n={}){let{parent:r,parentPath:i,schema:a}=pY(this,e,t,n.context);return a[p$](r&&r[i],pU({},n,{parent:r,path:e}))};for(let pz of["equals","is"])pH.prototype[pz]=pH.prototype.oneOf;for(let pG of["not","nope"])pH.prototype[pG]=pH.prototype.notOneOf;pH.prototype.optional=pH.prototype.notRequired;let pW=pH;function pK(){return new pW}pK.prototype=pW.prototype;let pV=e=>null==e;function pq(){return new pZ}class pZ extends pH{constructor(){super({type:"boolean"}),this.withMutation(()=>{this.transform(function(e){if(!this.isType(e)){if(/^(true|1)$/i.test(String(e)))return!0;if(/^(false|0)$/i.test(String(e)))return!1}return e})})}_typeCheck(e){return e instanceof Boolean&&(e=e.valueOf()),"boolean"==typeof e}isTrue(e=pm.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"true"},test:e=>pV(e)||!0===e})}isFalse(e=pm.isValue){return this.test({message:e,name:"is-value",exclusive:!0,params:{value:"false"},test:e=>pV(e)||!1===e})}}pq.prototype=pZ.prototype;let pX=/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i,pJ=/^((https?|ftp):)?\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i,pQ=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i,p1=e=>pV(e)||e===e.trim(),p0=({}).toString();function p2(){return new p3}class p3 extends pH{constructor(){super({type:"string"}),this.withMutation(()=>{this.transform(function(e){if(this.isType(e)||Array.isArray(e))return e;let t=null!=e&&e.toString?e.toString():e;return t===p0?e:t})})}_typeCheck(e){return e instanceof String&&(e=e.valueOf()),"string"==typeof e}_isPresent(e){return super._isPresent(e)&&!!e.length}length(e,t=ph.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pV(t)||t.length===this.resolve(e)}})}min(e,t=ph.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t.length>=this.resolve(e)}})}max(e,t=ph.max){return this.test({name:"max",exclusive:!0,message:t,params:{max:e},test(t){return pV(t)||t.length<=this.resolve(e)}})}matches(e,t){let n=!1,r,i;return t&&("object"==typeof t?{excludeEmptyString:n=!1,message:r,name:i}=t:r=t),this.test({name:i||"matches",message:r||ph.matches,params:{regex:e},test:t=>pV(t)||""===t&&n||-1!==t.search(e)})}email(e=ph.email){return this.matches(pX,{name:"email",message:e,excludeEmptyString:!0})}url(e=ph.url){return this.matches(pJ,{name:"url",message:e,excludeEmptyString:!0})}uuid(e=ph.uuid){return this.matches(pQ,{name:"uuid",message:e,excludeEmptyString:!1})}ensure(){return this.default("").transform(e=>null===e?"":e)}trim(e=ph.trim){return this.transform(e=>null!=e?e.trim():e).test({message:e,name:"trim",test:p1})}lowercase(e=ph.lowercase){return this.transform(e=>pV(e)?e:e.toLowerCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pV(e)||e===e.toLowerCase()})}uppercase(e=ph.uppercase){return this.transform(e=>pV(e)?e:e.toUpperCase()).test({message:e,name:"string_case",exclusive:!0,test:e=>pV(e)||e===e.toUpperCase()})}}p2.prototype=p3.prototype;let p4=e=>e!=+e;function p5(){return new p6}class p6 extends pH{constructor(){super({type:"number"}),this.withMutation(()=>{this.transform(function(e){let t=e;if("string"==typeof t){if(""===(t=t.replace(/\s/g,"")))return NaN;t=+t}return this.isType(t)?t:parseFloat(t)})})}_typeCheck(e){return e instanceof Number&&(e=e.valueOf()),"number"==typeof e&&!p4(e)}min(e,t=pp.min){return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t>=this.resolve(e)}})}max(e,t=pp.max){return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pV(t)||t<=this.resolve(e)}})}lessThan(e,t=pp.lessThan){return this.test({message:t,name:"max",exclusive:!0,params:{less:e},test(t){return pV(t)||tthis.resolve(e)}})}positive(e=pp.positive){return this.moreThan(0,e)}negative(e=pp.negative){return this.lessThan(0,e)}integer(e=pp.integer){return this.test({name:"integer",message:e,test:e=>pV(e)||Number.isInteger(e)})}truncate(){return this.transform(e=>pV(e)?e:0|e)}round(e){var t,n=["ceil","floor","round","trunc"];if("trunc"===(e=(null==(t=e)?void 0:t.toLowerCase())||"round"))return this.truncate();if(-1===n.indexOf(e.toLowerCase()))throw TypeError("Only valid options for round() are: "+n.join(", "));return this.transform(t=>pV(t)?t:Math[e](t))}}p5.prototype=p6.prototype;var p9=/^(\d{4}|[+\-]\d{6})(?:-?(\d{2})(?:-?(\d{2}))?)?(?:[ T]?(\d{2}):?(\d{2})(?::?(\d{2})(?:[,\.](\d{1,}))?)?(?:(Z)|([+\-])(\d{2})(?::?(\d{2}))?)?)?$/;function p8(e){var t,n,r=[1,4,5,6,7,10,11],i=0;if(n=p9.exec(e)){for(var a,o=0;a=r[o];++o)n[a]=+n[a]||0;n[2]=(+n[2]||1)-1,n[3]=+n[3]||1,n[7]=n[7]?String(n[7]).substr(0,3):0,(void 0===n[8]||""===n[8])&&(void 0===n[9]||""===n[9])?t=+new Date(n[1],n[2],n[3],n[4],n[5],n[6],n[7]):("Z"!==n[8]&&void 0!==n[9]&&(i=60*n[10]+n[11],"+"===n[9]&&(i=0-i)),t=Date.UTC(n[1],n[2],n[3],n[4],n[5]+i,n[6],n[7]))}else t=Date.parse?Date.parse(e):NaN;return t}let p7=new Date(""),be=e=>"[object Date]"===Object.prototype.toString.call(e);function bt(){return new bn}class bn extends pH{constructor(){super({type:"date"}),this.withMutation(()=>{this.transform(function(e){return this.isType(e)?e:(e=p8(e),isNaN(e)?p7:new Date(e))})})}_typeCheck(e){return be(e)&&!isNaN(e.getTime())}prepareParam(e,t){let n;if(pN.isRef(e))n=e;else{let r=this.cast(e);if(!this._typeCheck(r))throw TypeError(`\`${t}\` must be a Date or a value that can be \`cast()\` to a Date`);n=r}return n}min(e,t=pb.min){let n=this.prepareParam(e,"min");return this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(e){return pV(e)||e>=this.resolve(n)}})}max(e,t=pb.max){var n=this.prepareParam(e,"max");return this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(e){return pV(e)||e<=this.resolve(n)}})}}bn.INVALID_DATE=p7,bt.prototype=bn.prototype,bt.INVALID_DATE=p7;var br=n(11865),bi=n.n(br),ba=n(68929),bo=n.n(ba),bs=n(67523),bu=n.n(bs),bc=n(94633),bl=n.n(bc);function bf(e,t=[]){let n=[],r=[];function i(e,i){var a=(0,pI.split)(e)[0];~r.indexOf(a)||r.push(a),~t.indexOf(`${i}-${a}`)||n.push([i,a])}for(let a in e)if(pw()(e,a)){let o=e[a];~r.indexOf(a)||r.push(a),pN.isRef(o)&&o.isSibling?i(o.path,a):p_(o)&&"deps"in o&&o.deps.forEach(e=>i(e,a))}return bl().array(r,n).reverse()}function bd(e,t){let n=1/0;return e.some((e,r)=>{var i;if((null==(i=t.path)?void 0:i.indexOf(e))!==-1)return n=r,!0}),n}function bh(e){return(t,n)=>bd(e,t)-bd(e,n)}function bp(){return(bp=Object.assign||function(e){for(var t=1;t"[object Object]"===Object.prototype.toString.call(e);function bm(e,t){let n=Object.keys(e.fields);return Object.keys(t).filter(e=>-1===n.indexOf(e))}let bg=bh([]);class bv extends pH{constructor(e){super({type:"object"}),this.fields=Object.create(null),this._sortErrors=bg,this._nodes=[],this._excludedEdges=[],this.withMutation(()=>{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null}),e&&this.shape(e)})}_typeCheck(e){return bb(e)||"function"==typeof e}_cast(e,t={}){var n;let r=super._cast(e,t);if(void 0===r)return this.getDefault();if(!this._typeCheck(r))return r;let i=this.fields,a=null!=(n=t.stripUnknown)?n:this.spec.noUnknown,o=this._nodes.concat(Object.keys(r).filter(e=>-1===this._nodes.indexOf(e))),s={},u=bp({},t,{parent:s,__validating:t.__validating||!1}),c=!1;for(let l of o){let f=i[l],d=pw()(r,l);if(f){let h,p=r[l];u.path=(t.path?`${t.path}.`:"")+l;let b="spec"in(f=f.resolve({value:p,context:t.context,parent:s}))?f.spec:void 0,m=null==b?void 0:b.strict;if(null==b?void 0:b.strip){c=c||l in r;continue}void 0!==(h=t.__validating&&m?r[l]:f.cast(r[l],u))&&(s[l]=h)}else d&&!a&&(s[l]=r[l]);s[l]!==r[l]&&(c=!0)}return c?s:r}_validate(e,t={},n){let r=[],{sync:i,from:a=[],originalValue:o=e,abortEarly:s=this.spec.abortEarly,recursive:u=this.spec.recursive}=t;a=[{schema:this,value:o},...a],t.__validating=!0,t.originalValue=o,t.from=a,super._validate(e,t,(e,c)=>{if(e){if(!pM.isError(e)||s)return void n(e,c);r.push(e)}if(!u||!bb(c)){n(r[0]||null,c);return}o=o||c;let l=this._nodes.map(e=>(n,r)=>{let i=-1===e.indexOf(".")?(t.path?`${t.path}.`:"")+e:`${t.path||""}["${e}"]`,s=this.fields[e];if(s&&"validate"in s){s.validate(c[e],bp({},t,{path:i,from:a,strict:!0,parent:c,originalValue:o[e]}),r);return}r(null)});pA({sync:i,tests:l,value:c,errors:r,endEarly:s,sort:this._sortErrors,path:t.path},n)})}clone(e){let t=super.clone(e);return t.fields=bp({},this.fields),t._nodes=this._nodes,t._excludedEdges=this._excludedEdges,t._sortErrors=this._sortErrors,t}concat(e){let t=super.concat(e),n=t.fields;for(let[r,i]of Object.entries(this.fields)){let a=n[r];void 0===a?n[r]=i:a instanceof pH&&i instanceof pH&&(n[r]=i.concat(a))}return t.withMutation(()=>t.shape(n))}getDefaultFromShape(){let e={};return this._nodes.forEach(t=>{let n=this.fields[t];e[t]="default"in n?n.getDefault():void 0}),e}_getDefault(){return"default"in this.spec?super._getDefault():this._nodes.length?this.getDefaultFromShape():void 0}shape(e,t=[]){let n=this.clone(),r=Object.assign(n.fields,e);if(n.fields=r,n._sortErrors=bh(Object.keys(r)),t.length){Array.isArray(t[0])||(t=[t]);let i=t.map(([e,t])=>`${e}-${t}`);n._excludedEdges=n._excludedEdges.concat(i)}return n._nodes=bf(r,n._excludedEdges),n}pick(e){let t={};for(let n of e)this.fields[n]&&(t[n]=this.fields[n]);return this.clone().withMutation(e=>(e.fields={},e.shape(t)))}omit(e){let t=this.clone(),n=t.fields;for(let r of(t.fields={},e))delete n[r];return t.withMutation(()=>t.shape(n))}from(e,t,n){let r=(0,pI.getter)(e,!0);return this.transform(i=>{if(null==i)return i;let a=i;return pw()(i,e)&&(a=bp({},i),n||delete a[e],a[t]=r(i)),a})}noUnknown(e=!0,t=pg.noUnknown){"string"==typeof e&&(t=e,e=!0);let n=this.test({name:"noUnknown",exclusive:!0,message:t,test(t){if(null==t)return!0;let n=bm(this.schema,t);return!e||0===n.length||this.createError({params:{unknown:n.join(", ")}})}});return n.spec.noUnknown=e,n}unknown(e=!0,t=pg.noUnknown){return this.noUnknown(!e,t)}transformKeys(e){return this.transform(t=>t&&bu()(t,(t,n)=>e(n)))}camelCase(){return this.transformKeys(bo())}snakeCase(){return this.transformKeys(bi())}constantCase(){return this.transformKeys(e=>bi()(e).toUpperCase())}describe(){let e=super.describe();return e.fields=pC()(this.fields,e=>e.describe()),e}}function by(e){return new bv(e)}function bw(){return(bw=Object.assign||function(e){for(var t=1;t{this.transform(function(e){if("string"==typeof e)try{e=JSON.parse(e)}catch(t){e=null}return this.isType(e)?e:null})})}_typeCheck(e){return Array.isArray(e)}get _subType(){return this.innerType}_cast(e,t){let n=super._cast(e,t);if(!this._typeCheck(n)||!this.innerType)return n;let r=!1,i=n.map((e,n)=>{let i=this.innerType.cast(e,bw({},t,{path:`${t.path||""}[${n}]`}));return i!==e&&(r=!0),i});return r?i:n}_validate(e,t={},n){var r,i;let a=[],o=t.sync,s=t.path,u=this.innerType,c=null!=(r=t.abortEarly)?r:this.spec.abortEarly,l=null!=(i=t.recursive)?i:this.spec.recursive,f=null!=t.originalValue?t.originalValue:e;super._validate(e,t,(e,r)=>{if(e){if(!pM.isError(e)||c)return void n(e,r);a.push(e)}if(!l||!u||!this._typeCheck(r)){n(a[0]||null,r);return}f=f||r;let i=Array(r.length);for(let d=0;du.validate(h,b,t)}pA({sync:o,path:s,value:r,errors:a,endEarly:c,tests:i},n)})}clone(e){let t=super.clone(e);return t.innerType=this.innerType,t}concat(e){let t=super.concat(e);return t.innerType=this.innerType,e.innerType&&(t.innerType=t.innerType?t.innerType.concat(e.innerType):e.innerType),t}of(e){let t=this.clone();if(!p_(e))throw TypeError("`array.of()` sub-schema must be a valid yup schema not: "+pf(e));return t.innerType=e,t}length(e,t=pv.length){return this.test({message:t,name:"length",exclusive:!0,params:{length:e},test(t){return pV(t)||t.length===this.resolve(e)}})}min(e,t){return t=t||pv.min,this.test({message:t,name:"min",exclusive:!0,params:{min:e},test(t){return pV(t)||t.length>=this.resolve(e)}})}max(e,t){return t=t||pv.max,this.test({message:t,name:"max",exclusive:!0,params:{max:e},test(t){return pV(t)||t.length<=this.resolve(e)}})}ensure(){return this.default(()=>[]).transform((e,t)=>this._typeCheck(e)?e:null==t?[]:[].concat(t))}compact(e){let t=e?(t,n,r)=>!e(t,n,r):e=>!!e;return this.transform(e=>null!=e?e.filter(t):e)}describe(){let e=super.describe();return this.innerType&&(e.innerType=this.innerType.describe()),e}nullable(e=!0){return super.nullable(e)}defined(){return super.defined()}required(e){return super.required(e)}}b_.prototype=bE.prototype;var bS=by().shape({name:p2().required("Required"),url:p2().required("Required")}),bk=function(e){var t=e.initialValues,n=e.onSubmit,r=e.submitButtonText,i=e.nameDisabled,a=void 0!==i&&i;return l.createElement(hM,{initialValues:t,validationSchema:bS,onSubmit:n},function(e){var t=e.isSubmitting;return l.createElement(l.Fragment,null,l.createElement(hj,{"data-testid":"bridge-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hR,{component:hJ,id:"name",name:"name",label:"Name",disabled:a,required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(hR,{component:hJ,id:"url",name:"url",label:"Bridge URL",placeholder:"https://",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"url-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:7},l.createElement(hR,{component:hJ,id:"minimumContractPayment",name:"minimumContractPayment",label:"Minimum Contract Payment",placeholder:"0",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"minimumContractPayment-helper-text"}})),l.createElement(d.Z,{item:!0,xs:7},l.createElement(hR,{component:hJ,id:"confirmations",name:"confirmations",label:"Confirmations",placeholder:"0",type:"number",fullWidth:!0,inputProps:{min:0},FormHelperTextProps:{"data-testid":"confirmations-helper-text"}})))),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ox.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},r)))))})},bx=function(e){var t=e.bridge,n=e.onSubmit,r={name:t.name,url:t.url,minimumContractPayment:t.minimumContractPayment,confirmations:t.confirmations};return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:40},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Edit Bridge",action:l.createElement(aL.Z,{component:tz,href:"/bridges/".concat(t.id)},"Cancel")}),l.createElement(aK.Z,null,l.createElement(bk,{nameDisabled:!0,initialValues:r,onSubmit:n,submitButtonText:"Save Bridge"}))))))};function bT(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]&&arguments[0],t=e?function(){return l.createElement(x.default,{variant:"body1"},"Loading...")}:function(){return null};return{isLoading:e,LoadingPlaceholder:t}},ml=n(76023);function mf(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=0||(i[n]=e[n]);return i}function mB(e,t){if(null==e)return{};var n,r,i=mY(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function mU(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=4?[e[0],e[1],e[2],e[3],"".concat(e[0],".").concat(e[1]),"".concat(e[0],".").concat(e[2]),"".concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[0]),"".concat(e[1],".").concat(e[2]),"".concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[1]),"".concat(e[2],".").concat(e[3]),"".concat(e[3],".").concat(e[0]),"".concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[0]),"".concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[0],".").concat(e[1],".").concat(e[2],".").concat(e[3]),"".concat(e[0],".").concat(e[1],".").concat(e[3],".").concat(e[2]),"".concat(e[0],".").concat(e[2],".").concat(e[1],".").concat(e[3]),"".concat(e[0],".").concat(e[2],".").concat(e[3],".").concat(e[1]),"".concat(e[0],".").concat(e[3],".").concat(e[1],".").concat(e[2]),"".concat(e[0],".").concat(e[3],".").concat(e[2],".").concat(e[1]),"".concat(e[1],".").concat(e[0],".").concat(e[2],".").concat(e[3]),"".concat(e[1],".").concat(e[0],".").concat(e[3],".").concat(e[2]),"".concat(e[1],".").concat(e[2],".").concat(e[0],".").concat(e[3]),"".concat(e[1],".").concat(e[2],".").concat(e[3],".").concat(e[0]),"".concat(e[1],".").concat(e[3],".").concat(e[0],".").concat(e[2]),"".concat(e[1],".").concat(e[3],".").concat(e[2],".").concat(e[0]),"".concat(e[2],".").concat(e[0],".").concat(e[1],".").concat(e[3]),"".concat(e[2],".").concat(e[0],".").concat(e[3],".").concat(e[1]),"".concat(e[2],".").concat(e[1],".").concat(e[0],".").concat(e[3]),"".concat(e[2],".").concat(e[1],".").concat(e[3],".").concat(e[0]),"".concat(e[2],".").concat(e[3],".").concat(e[0],".").concat(e[1]),"".concat(e[2],".").concat(e[3],".").concat(e[1],".").concat(e[0]),"".concat(e[3],".").concat(e[0],".").concat(e[1],".").concat(e[2]),"".concat(e[3],".").concat(e[0],".").concat(e[2],".").concat(e[1]),"".concat(e[3],".").concat(e[1],".").concat(e[0],".").concat(e[2]),"".concat(e[3],".").concat(e[1],".").concat(e[2],".").concat(e[0]),"".concat(e[3],".").concat(e[2],".").concat(e[0],".").concat(e[1]),"".concat(e[3],".").concat(e[2],".").concat(e[1],".").concat(e[0])]:void 0}var mX={};function mJ(e){if(0===e.length||1===e.length)return e;var t=e.join(".");return mX[t]||(mX[t]=mZ(e)),mX[t]}function mQ(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2?arguments[2]:void 0;return mJ(e.filter(function(e){return"token"!==e})).reduce(function(e,t){return mV({},e,n[t])},t)}function m1(e){return e.join(" ")}function m0(e,t){var n=0;return function(r){return n+=1,r.map(function(r,i){return m2({node:r,stylesheet:e,useInlineStyles:t,key:"code-segment-".concat(n,"-").concat(i)})})}}function m2(e){var t=e.node,n=e.stylesheet,r=e.style,i=void 0===r?{}:r,a=e.useInlineStyles,o=e.key,s=t.properties,u=t.type,c=t.tagName,f=t.value;if("text"===u)return f;if(c){var d,h=m0(n,a);if(a){var p=Object.keys(n).reduce(function(e,t){return t.split(".").forEach(function(t){e.includes(t)||e.push(t)}),e},[]),b=s.className&&s.className.includes("token")?["token"]:[],m=s.className&&b.concat(s.className.filter(function(e){return!p.includes(e)}));d=mV({},s,{className:m1(m)||void 0,style:mQ(s.className,Object.assign({},s.style,i),n)})}else d=mV({},s,{className:m1(s.className)});var g=h(t.children);return l.createElement(c,mq({key:o},d),g)}}let m3=function(e,t){return -1!==e.listLanguages().indexOf(t)};var m4=/\n/g;function m5(e){return e.match(m4)}function m6(e){var t=e.lines,n=e.startingLineNumber,r=e.style;return t.map(function(e,t){var i=t+n;return l.createElement("span",{key:"line-".concat(t),className:"react-syntax-highlighter-line-number",style:"function"==typeof r?r(i):r},"".concat(i,"\n"))})}function m9(e){var t=e.codeString,n=e.codeStyle,r=e.containerStyle,i=void 0===r?{float:"left",paddingRight:"10px"}:r,a=e.numberStyle,o=void 0===a?{}:a,s=e.startingLineNumber;return l.createElement("code",{style:Object.assign({},n,i)},m6({lines:t.replace(/\n$/,"").split("\n"),style:o,startingLineNumber:s}))}function m8(e){return"".concat(e.toString().length,".25em")}function m7(e,t){return{type:"element",tagName:"span",properties:{key:"line-number--".concat(e),className:["comment","linenumber","react-syntax-highlighter-line-number"],style:t},children:[{type:"text",value:e}]}}function ge(e,t,n){var r,i={display:"inline-block",minWidth:m8(n),paddingRight:"1em",textAlign:"right",userSelect:"none"};return mV({},i,"function"==typeof e?e(t):e)}function gt(e){var t=e.children,n=e.lineNumber,r=e.lineNumberStyle,i=e.largestLineNumber,a=e.showInlineLineNumbers,o=e.lineProps,s=void 0===o?{}:o,u=e.className,c=void 0===u?[]:u,l=e.showLineNumbers,f=e.wrapLongLines,d="function"==typeof s?s(n):s;if(d.className=c,n&&a){var h=ge(r,n,i);t.unshift(m7(n,h))}return f&l&&(d.style=mV({},d.style,{display:"flex"})),{type:"element",tagName:"span",properties:d,children:t}}function gn(e){for(var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[],n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],r=0;r2&&void 0!==arguments[2]?arguments[2]:[];return gt({children:e,lineNumber:t,lineNumberStyle:s,largestLineNumber:o,showInlineLineNumbers:i,lineProps:n,className:a,showLineNumbers:r,wrapLongLines:u})}function b(e,t){if(r&&t&&i){var n=ge(s,t,o);e.unshift(m7(t,n))}return e}function m(e,n){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[];return t||r.length>0?p(e,n,r):b(e,n)}for(var g=function(){var e=l[h],t=e.children[0].value;if(m5(t)){var n=t.split("\n");n.forEach(function(t,i){var o=r&&f.length+a,s={type:"text",value:"".concat(t,"\n")};if(0===i){var u=l.slice(d+1,h).concat(gt({children:[s],className:e.properties.className})),c=m(u,o);f.push(c)}else if(i===n.length-1){if(l[h+1]&&l[h+1].children&&l[h+1].children[0]){var p={type:"text",value:"".concat(t)},b=gt({children:[p],className:e.properties.className});l.splice(h+1,0,b)}else{var g=[s],v=m(g,o,e.properties.className);f.push(v)}}else{var y=[s],w=m(y,o,e.properties.className);f.push(w)}}),d=h}h++};h code[class*="language-"]':{background:"#f5f2f0",padding:".1em",borderRadius:".3em",whiteSpace:"normal"},comment:{color:"slategray"},prolog:{color:"slategray"},doctype:{color:"slategray"},cdata:{color:"slategray"},punctuation:{color:"#999"},namespace:{Opacity:".7"},property:{color:"#905"},tag:{color:"#905"},boolean:{color:"#905"},number:{color:"#905"},constant:{color:"#905"},symbol:{color:"#905"},deleted:{color:"#905"},selector:{color:"#690"},"attr-name":{color:"#690"},string:{color:"#690"},char:{color:"#690"},builtin:{color:"#690"},inserted:{color:"#690"},operator:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},entity:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)",cursor:"help"},url:{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".language-css .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},".style .token.string":{color:"#9a6e3a",background:"hsla(0, 0%, 100%, .5)"},atrule:{color:"#07a"},"attr-value":{color:"#07a"},keyword:{color:"#07a"},function:{color:"#DD4A68"},"class-name":{color:"#DD4A68"},regex:{color:"#e90"},important:{color:"#e90",fontWeight:"bold"},variable:{color:"#e90"},bold:{fontWeight:"bold"},italic:{fontStyle:"italic"}};var gc=n(98695),gl=n.n(gc);let gf=["abap","abnf","actionscript","ada","agda","al","antlr4","apacheconf","apl","applescript","aql","arduino","arff","asciidoc","asm6502","aspnet","autohotkey","autoit","bash","basic","batch","bbcode","birb","bison","bnf","brainfuck","brightscript","bro","bsl","c","cil","clike","clojure","cmake","coffeescript","concurnas","cpp","crystal","csharp","csp","css-extras","css","cypher","d","dart","dax","dhall","diff","django","dns-zone-file","docker","ebnf","editorconfig","eiffel","ejs","elixir","elm","erb","erlang","etlua","excel-formula","factor","firestore-security-rules","flow","fortran","fsharp","ftl","gcode","gdscript","gedcom","gherkin","git","glsl","gml","go","graphql","groovy","haml","handlebars","haskell","haxe","hcl","hlsl","hpkp","hsts","http","ichigojam","icon","iecst","ignore","inform7","ini","io","j","java","javadoc","javadoclike","javascript","javastacktrace","jolie","jq","js-extras","js-templates","jsdoc","json","json5","jsonp","jsstacktrace","jsx","julia","keyman","kotlin","latex","latte","less","lilypond","liquid","lisp","livescript","llvm","lolcode","lua","makefile","markdown","markup-templating","markup","matlab","mel","mizar","mongodb","monkey","moonscript","n1ql","n4js","nand2tetris-hdl","naniscript","nasm","neon","nginx","nim","nix","nsis","objectivec","ocaml","opencl","oz","parigp","parser","pascal","pascaligo","pcaxis","peoplecode","perl","php-extras","php","phpdoc","plsql","powerquery","powershell","processing","prolog","properties","protobuf","pug","puppet","pure","purebasic","purescript","python","q","qml","qore","r","racket","reason","regex","renpy","rest","rip","roboconf","robotframework","ruby","rust","sas","sass","scala","scheme","scss","shell-session","smali","smalltalk","smarty","sml","solidity","solution-file","soy","sparql","splunk-spl","sqf","sql","stan","stylus","swift","t4-cs","t4-templating","t4-vb","tap","tcl","textile","toml","tsx","tt2","turtle","twig","typescript","typoscript","unrealscript","vala","vbnet","velocity","verilog","vhdl","vim","visual-basic","warpscript","wasm","wiki","xeora","xml-doc","xojo","xquery","yaml","yang","zig"];var gd=gs(gl(),gu);gd.supportedLanguages=gf;let gh=gd;var gp=n(64566);function gb(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function gm(){var e=gb(["\n query FetchConfigV2 {\n configv2 {\n user\n effective\n }\n }\n"]);return gm=function(){return e},e}var gg=n0(gm()),gv=function(e){var t=e.children;return l.createElement(ii.Z,null,l.createElement(ie.default,{component:"th",scope:"row",colSpan:3},t))},gy=function(){return l.createElement(gv,null,"...")},gw=function(e){var t=e.children;return l.createElement(gv,null,t)},g_=function(e){var t=e.loading,n=e.toml,r=e.error,i=void 0===r?"":r,a=e.title,o=e.expanded;if(i)return l.createElement(gw,null,i);if(t)return l.createElement(gy,null);a||(a="TOML");var s={display:"block"};return l.createElement(x.default,null,l.createElement(mR.Z,{defaultExpanded:o},l.createElement(mj.Z,{expandIcon:l.createElement(gp.Z,null)},a),l.createElement(mF.Z,{style:s},l.createElement(gh,{language:"toml",style:gu},n))))},gE=function(){var e=ry(gg,{fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return(null==t?void 0:t.configv2.effective)=="N/A"?l.createElement(l.Fragment,null,l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"TOML Configuration"}),l.createElement(g_,{title:"V2 config dump:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0})))):l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"TOML Configuration"}),l.createElement(g_,{title:"User specified:",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.user,showHead:!0,expanded:!0}),l.createElement(g_,{title:"Effective (with defaults):",error:null==r?void 0:r.message,loading:n,toml:null==t?void 0:t.configv2.effective,showHead:!0})))))},gS=n(34823),gk=function(e){return(0,b.createStyles)({cell:{paddingTop:1.5*e.spacing.unit,paddingBottom:1.5*e.spacing.unit}})},gx=(0,b.withStyles)(gk)(function(e){var t=e.classes,n=(0,A.I0)();(0,l.useEffect)(function(){n((0,ty.DQ)())});var r=(0,A.v9)(gS.N,A.wU);return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Node"}),l.createElement(r8.Z,null,l.createElement(r7.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,{className:t.cell},l.createElement(x.default,null,"Version"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.version))),l.createElement(ii.Z,null,l.createElement(ie.default,{className:t.cell},l.createElement(x.default,null,"SHA"),l.createElement(x.default,{variant:"subtitle1",color:"textSecondary"},r.commitSHA))))))}),gT=function(){return l.createElement(iv,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,sm:12,md:8},l.createElement(d.Z,{container:!0},l.createElement(gE,null))),l.createElement(d.Z,{item:!0,sm:12,md:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gx,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mP,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(mS,null))))))},gM=function(){return l.createElement(gT,null)},gO=function(){return l.createElement(gM,null)},gA=n(44431),gL=1e18,gC=function(e){return new gA.BigNumber(e).dividedBy(gL).toFixed(8)},gI=function(e){var t=e.keys,n=e.chainID,r=e.hideHeaderTitle;return l.createElement(l.Fragment,null,l.createElement(sf.Z,{title:!r&&"Account Balances",subheader:"Chain ID "+n}),l.createElement(aK.Z,null,l.createElement(w.default,{dense:!1,disablePadding:!0},t&&t.map(function(e,r){return l.createElement(l.Fragment,null,l.createElement(_.default,{disableGutters:!0,key:["acc-balance",n.toString(),r.toString()].join("-")},l.createElement(E.Z,{primary:l.createElement(l.Fragment,null,l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ob,{title:"Address"}),l.createElement(om,{value:e.address})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ob,{title:"Native Token Balance"}),l.createElement(om,{value:e.ethBalance||"--"})),l.createElement(d.Z,{item:!0,xs:6},l.createElement(ob,{title:"LINK Balance"}),l.createElement(om,{value:e.linkBalance?gC(e.linkBalance):"--"}))))})),r+1s&&l.createElement(gU.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,{className:r.footer},l.createElement(aL.Z,{href:"/runs",component:tz},"View More"))))))});function vn(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vr(){var e=vn(["\n ","\n query FetchRecentJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...RecentJobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return vr=function(){return e},e}var vi=5,va=n0(vr(),g7),vo=function(){var e=ry(va,{variables:{offset:0,limit:vi},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vt,{data:t,errorMsg:null==r?void 0:r.message,loading:n,maxRunsSize:vi})},vs=function(e){return(0,b.createStyles)({style:{textAlign:"center",padding:2.5*e.spacing.unit,position:"fixed",left:"0",bottom:"0",width:"100%",borderRadius:0},bareAnchor:{color:e.palette.common.black,textDecoration:"none"}})},vu=(0,b.withStyles)(vs)(function(e){var t=e.classes,n=(0,A.v9)(gS.N,A.wU),r=(0,A.I0)();return(0,l.useEffect)(function(){r((0,ty.DQ)())}),l.createElement(ia.default,{className:t.style},l.createElement(x.default,null,"Chainlink Node ",n.version," at commit"," ",l.createElement("a",{target:"_blank",rel:"noopener noreferrer",href:"https://github.com/smartcontractkit/chainlink/commit/".concat(n.commitSHA),className:t.bareAnchor},n.commitSHA)))}),vc=function(e){return(0,b.createStyles)({cell:{borderColor:e.palette.divider,borderTop:"1px solid",borderBottom:"none",paddingTop:2*e.spacing.unit,paddingBottom:2*e.spacing.unit,paddingLeft:2*e.spacing.unit},block:{display:"block"},overflowEllipsis:{textOverflow:"ellipsis",overflow:"hidden"}})},vl=(0,b.withStyles)(vc)(function(e){var t=e.classes,n=e.job;return l.createElement(ii.Z,null,l.createElement(ie.default,{scope:"row",className:t.cell},l.createElement(d.Z,{container:!0,spacing:0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(ip,{href:"/jobs/".concat(n.id),classes:{linkContent:t.block}},l.createElement(x.default,{className:t.overflowEllipsis,variant:"body1",component:"span",color:"primary"},n.name||n.id))),l.createElement(d.Z,{item:!0,xs:12},l.createElement(x.default,{variant:"body1",color:"textSecondary"},"Created ",l.createElement(aA,{tooltip:!0},n.createdAt))))))});function vf(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vd(){var e=vf(["\n fragment RecentJobsPayload_ResultsFields on Job {\n id\n name\n createdAt\n }\n"]);return vd=function(){return e},e}var vh=n0(vd()),vp=function(){return(0,b.createStyles)({cardHeader:{borderBottom:0},table:{tableLayout:"fixed"}})},vb=(0,b.withStyles)(vp)(function(e){var t,n,r=e.classes,i=e.data,a=e.errorMsg,o=e.loading;return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Recent Jobs",className:r.cardHeader}),l.createElement(r8.Z,{className:r.table},l.createElement(r7.Z,null,l.createElement(gz,{visible:o}),l.createElement(gG,{visible:(null===(t=null==i?void 0:i.jobs.results)||void 0===t?void 0:t.length)===0},"No recently created jobs"),l.createElement(gH,{msg:a}),null===(n=null==i?void 0:i.jobs.results)||void 0===n?void 0:n.map(function(e,t){return l.createElement(vl,{job:e,key:t})}))))});function vm(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function vg(){var e=vm(["\n ","\n query FetchRecentJobs($offset: Int, $limit: Int) {\n jobs(offset: $offset, limit: $limit) {\n results {\n ...RecentJobsPayload_ResultsFields\n }\n }\n }\n"]);return vg=function(){return e},e}var vv=5,vy=n0(vg(),vh),vw=function(){var e=ry(vy,{variables:{offset:0,limit:vv},fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error;return l.createElement(vb,{data:t,errorMsg:null==r?void 0:r.message,loading:n})},v_=function(){return l.createElement(iv,null,l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:8},l.createElement(vo,null)),l.createElement(d.Z,{item:!0,xs:4},l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12},l.createElement(gB,null)),l.createElement(d.Z,{item:!0,xs:12},l.createElement(vw,null))))),l.createElement(vu,null))},vE=function(){return l.createElement(v_,null)},vS=function(){return l.createElement(vE,null)},vk=n(87239),vx=function(e){switch(e){case"DirectRequestSpec":return"Direct Request";case"FluxMonitorSpec":return"Flux Monitor";default:return e.replace(/Spec$/,"")}},vT=n(5022),vM=n(78718),vO=n.n(vM);function vA(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1?t-1:0),r=1;r1?t-1:0),r=1;re.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&n.map(function(e){return l.createElement(ii.Z,{key:e.id,style:{cursor:"pointer"},onClick:function(){return r.push("/runs/".concat(e.id))}},l.createElement(ie.default,{className:t.idCell,scope:"row"},l.createElement("div",{className:t.runDetails},l.createElement(x.default,{variant:"h5",color:"primary",component:"span"},e.id))),l.createElement(ie.default,{className:t.stampCell},l.createElement(x.default,{variant:"body1",color:"textSecondary",className:t.stamp},"Created ",l.createElement(aA,{tooltip:!0},e.createdAt))),l.createElement(ie.default,{className:t.statusCell,scope:"row"},l.createElement(x.default,{variant:"body1",className:O()(t.status,yp(t,e.status))},e.status.toLowerCase())))})))}),ym=n(16839),yg=n.n(ym);function yv(e){var t=e.replace(/\w+\s*=\s*<([^>]|[\r\n])*>/g,""),n=yg().read(t),r=n.edges();return n.nodes().map(function(e){var t={id:e,parentIds:r.filter(function(t){return t.w===e}).map(function(e){return e.v})};return Object.keys(n.node(e)).length>0&&(t.attributes=n.node(e)),t})}var yy=n(94164),yw=function(e){var t=e.data,n=[];return(null==t?void 0:t.attributes)&&Object.keys(t.attributes).forEach(function(e){var r;n.push(l.createElement("div",{key:e},l.createElement(x.default,{variant:"body1",color:"textSecondary",component:"div"},l.createElement("b",null,e,":")," ",null===(r=t.attributes)||void 0===r?void 0:r[e])))}),l.createElement("div",null,t&&l.createElement(x.default,{variant:"body1",color:"textPrimary"},l.createElement("b",null,t.id)),n)},y_=n(73343),yE=n(3379),yS=n.n(yE);function yk(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nwindow.innerWidth?u-r.getBoundingClientRect().width-a:u+a,n=c+r.getBoundingClientRect().height+i>window.innerHeight?c-r.getBoundingClientRect().height-a:c+a,r.style.opacity=String(1),r.style.top="".concat(n,"px"),r.style.left="".concat(t,"px"),r.style.zIndex=String(1)}},h=function(e){var t=document.getElementById("tooltip-d3-chart-".concat(e));t&&(t.style.opacity=String(0),t.style.zIndex=String(-1))};return l.createElement("div",{style:{fontFamily:"sans-serif",fontWeight:"normal"}},l.createElement(yy.kJ,{id:"task-list-graph-d3",data:i,config:s,onMouseOverNode:d,onMouseOutNode:h},"D3 chart"),n.map(function(e){return l.createElement("div",{key:"d3-tooltip-key-".concat(e.id),id:"tooltip-d3-chart-".concat(e.id),style:{position:"absolute",opacity:"0",border:"1px solid rgba(0, 0, 0, 0.1)",padding:y_.r.spacing.unit,background:"white",borderRadius:5,zIndex:-1,inlineSize:"min-content"}},l.createElement(yw,{data:e}))}))};function yC(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);nyB&&l.createElement("div",{className:t.runDetails},l.createElement(aL.Z,{href:"/jobs/".concat(n.id,"/runs"),component:tz},"View more")))),l.createElement(d.Z,{item:!0,xs:12,sm:6},l.createElement(yY,{observationSource:n.observationSource})))});function y$(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&void 0!==arguments[0]?arguments[0]:"";try{return vT.parse(e),!0}catch(t){return!1}})}),wK=function(e){var t=e.initialValues,n=e.onSubmit,r=e.onTOMLChange;return l.createElement(hM,{initialValues:t,validationSchema:wW,onSubmit:n},function(e){var t=e.isSubmitting,n=e.values;return r&&r(n.toml),l.createElement(hj,{"data-testid":"job-form",noValidate:!0},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12},l.createElement(hR,{component:hJ,id:"toml",name:"toml",label:"Job Spec (TOML)",required:!0,fullWidth:!0,multiline:!0,rows:10,rowsMax:25,variant:"outlined",autoComplete:"off",FormHelperTextProps:{"data-testid":"toml-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:7},l.createElement(ox.default,{variant:"contained",color:"primary",type:"submit",disabled:t,size:"large"},"Create Job"))))})},wV=n(50109),wq="persistSpec";function wZ(e){var t=e.query,n=new URLSearchParams(t).get("definition");return n?(wV.t8(wq,n),{toml:n}):{toml:wV.U2(wq)||""}}var wX=function(e){var t=e.onSubmit,n=e.onTOMLChange,r=wZ({query:(0,h.TH)().search}),i=function(e){var t=e.replace(/[\u200B-\u200D\uFEFF]/g,"");wV.t8("".concat(wq),t),n&&n(t)};return l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"New Job"}),l.createElement(aK.Z,null,l.createElement(wK,{initialValues:r,onSubmit:t,onTOMLChange:i})))};function wJ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n1&&void 0!==arguments[1]?arguments[1]:{},n=t.start,r=void 0===n?6:n,i=t.end,a=void 0===i?4:i;return e.substring(0,r)+"..."+e.substring(e.length-a)}function _O(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(_K,e)},_q=function(){var e=_V({fetchPolicy:"cache-and-network"}),t=e.data,n=e.loading,r=e.error,i=e.refetch;return l.createElement(_H,{loading:n,data:t,errorMsg:null==r?void 0:r.message,refetch:i})},_Z=function(e){var t=e.csaKey;return l.createElement(ii.Z,{hover:!0},l.createElement(ie.default,null,l.createElement(x.default,{variant:"body1"},t.publicKey," ",l.createElement(_T,{data:t.publicKey}))))};function _X(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function _J(){var e=_X(["\n fragment CSAKeysPayload_ResultsFields on CSAKey {\n id\n publicKey\n }\n"]);return _J=function(){return e},e}var _Q=n0(_J()),_1=function(e){var t,n,r,i=e.data,a=e.errorMsg,o=e.loading,s=e.onCreate;return l.createElement(r9.Z,null,l.createElement(sf.Z,{action:(null===(t=null==i?void 0:i.csaKeys.results)||void 0===t?void 0:t.length)===0&&l.createElement(ox.default,{variant:"outlined",color:"primary",onClick:s},"New CSA Key"),title:"CSA Key",subheader:"Manage your CSA Key"}),l.createElement(r8.Z,null,l.createElement(it.Z,null,l.createElement(ii.Z,null,l.createElement(ie.default,null,"Public Key"))),l.createElement(r7.Z,null,l.createElement(gz,{visible:o}),l.createElement(gG,{visible:(null===(n=null==i?void 0:i.csaKeys.results)||void 0===n?void 0:n.length)===0}),l.createElement(gH,{msg:a}),null===(r=null==i?void 0:i.csaKeys.results)||void 0===r?void 0:r.map(function(e,t){return l.createElement(_Z,{csaKey:e,key:t})}))))};function _0(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(EO,e)};function EL(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(EQ,e)},E4=function(){return os(E1)},E5=function(){return os(E0)},E6=function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};return ry(E2,e)};function E9(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(SV,e)};function SZ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);n=0)&&Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i}function kq(e,t){if(null==e)return{};var n,r,i={},a=Object.keys(e);for(r=0;r=0||(i[n]=e[n]);return i}var kZ=function(e){var t=e.run,n=l.useMemo(function(){var e=t.inputs,n=t.outputs,r=t.taskRuns,i=kV(t,["inputs","outputs","taskRuns"]),a={};try{a=JSON.parse(e)}catch(o){a={}}return kK(kG({},i),{inputs:a,outputs:n,taskRuns:r})},[t]);return l.createElement(r9.Z,null,l.createElement(aK.Z,null,l.createElement(k$,{object:n})))};function kX(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function kJ(e){for(var t=1;t0&&l.createElement(ki,{errors:t.allErrors})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(h.rs,null,l.createElement(h.AW,{path:"".concat(n,"/json")},l.createElement(kZ,{run:t})),l.createElement(h.AW,{path:n},t.taskRuns.length>0&&l.createElement(kP,{taskRuns:t.taskRuns,observationSource:t.job.observationSource}))))))))};function k9(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function k8(){var e=k9(["\n ","\n query FetchJobRun($id: ID!) {\n jobRun(id: $id) {\n __typename\n ... on JobRun {\n ...JobRunPayload_Fields\n }\n ... on NotFoundError {\n message\n }\n }\n }\n"]);return k8=function(){return e},e}var k7=n0(k8(),k5),xe=function(){var e=ry(k7,{variables:{id:(0,h.UO)().id}}),t=e.data,n=e.loading,r=e.error;if(n)return l.createElement(ij,null);if(r)return l.createElement(iN,{error:r});var i=null==t?void 0:t.jobRun;switch(null==i?void 0:i.__typename){case"JobRun":return l.createElement(k6,{run:i});case"NotFoundError":return l.createElement(oo,null);default:return null}};function xt(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xn(){var e=xt(["\n fragment JobRunsPayload_ResultsFields on JobRun {\n id\n allErrors\n createdAt\n finishedAt\n status\n job {\n id\n }\n }\n"]);return xn=function(){return e},e}var xr=n0(xn()),xi=function(e){var t=e.loading,n=e.data,r=e.page,i=e.pageSize,a=(0,h.k6)(),o=l.useMemo(function(){return null==n?void 0:n.jobRuns.results.map(function(e){var t,n=e.allErrors,r=e.id,i=e.createdAt;return{id:r,createdAt:i,errors:n,finishedAt:e.finishedAt,status:e.status}})},[n]);return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(iw,null,"Job Runs")),t&&l.createElement(ij,null),n&&o&&l.createElement(d.Z,{item:!0,xs:12},l.createElement(r9.Z,null,l.createElement(yb,{runs:o}),l.createElement(ir.Z,{component:"div",count:n.jobRuns.metadata.total,rowsPerPage:i,rowsPerPageOptions:[i],page:r-1,onChangePage:function(e,t){a.push("/runs?page=".concat(t+1,"&per=").concat(i))},onChangeRowsPerPage:function(){},backIconButtonProps:{"aria-label":"prev-page"},nextIconButtonProps:{"aria-label":"next-page"}})))))};function xa(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xo(){var e=xa(["\n ","\n query FetchJobRuns($offset: Int, $limit: Int) {\n jobRuns(offset: $offset, limit: $limit) {\n results {\n ...JobRunsPayload_ResultsFields\n }\n metadata {\n total\n }\n }\n }\n"]);return xo=function(){return e},e}var xs=n0(xo(),xr),xu=function(){var e=iF(),t=parseInt(e.get("page")||"1",10),n=parseInt(e.get("per")||"25",10),r=ry(xs,{variables:{offset:(t-1)*n,limit:n},fetchPolicy:"cache-and-network"}),i=r.data,a=r.loading,o=r.error;return o?l.createElement(iN,{error:o}):l.createElement(xi,{loading:a,data:i,page:t,pageSize:n})},xc=function(){var e=(0,h.$B)().path;return l.createElement(h.rs,null,l.createElement(h.AW,{exact:!0,path:e},l.createElement(xu,null)),l.createElement(h.AW,{path:"".concat(e,"/:id")},l.createElement(xe,null)))},xl=by().shape({name:p2().required("Required"),uri:p2().required("Required"),publicKey:p2().required("Required")}),xf=function(e){var t=e.initialValues,n=e.onSubmit;return l.createElement(hM,{initialValues:t,validationSchema:xl,onSubmit:n},function(e){var t=e.isSubmitting,n=e.submitForm;return l.createElement(hj,{"data-testid":"feeds-manager-form"},l.createElement(d.Z,{container:!0,spacing:16},l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"name",name:"name",label:"Name",required:!0,fullWidth:!0,FormHelperTextProps:{"data-testid":"name-helper-text"}})),l.createElement(d.Z,{item:!0,xs:!1,md:6}),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"uri",name:"uri",label:"URI",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"uri-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12,md:6},l.createElement(hR,{component:hJ,id:"publicKey",name:"publicKey",label:"Public Key",required:!0,fullWidth:!0,helperText:"Provided by the Feeds Manager operator",FormHelperTextProps:{"data-testid":"publicKey-helper-text"}})),l.createElement(d.Z,{item:!0,xs:12},l.createElement(ox.default,{variant:"contained",color:"primary",disabled:t,onClick:n},"Submit"))))})},xd=function(e){var t=e.data,n=e.onSubmit,r={name:t.name,uri:t.uri,publicKey:t.publicKey};return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Edit Feeds Manager"}),l.createElement(aK.Z,null,l.createElement(xf,{initialValues:r,onSubmit:n})))))};function xh(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function xp(){var e=xh(["\n query FetchFeedsManagers {\n feedsManagers {\n results {\n __typename\n id\n name\n uri\n publicKey\n isConnectionActive\n createdAt\n }\n }\n }\n"]);return xp=function(){return e},e}var xb=n0(xp()),xm=function(){return ry(xb)};function xg(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&void 0!==arguments[0]?arguments[0]:{};return ry(xZ,e)};function xJ(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);n0?n.feedsManagers.results[0]:void 0;return n&&a?l.createElement(TH,{manager:a}):l.createElement(h.l_,{to:{pathname:"/feeds_manager/new",state:{from:e}}})},Tz={name:"Chainlink Feeds Manager",uri:"",publicKey:""},TG=function(e){var t=e.onSubmit;return l.createElement(d.Z,{container:!0},l.createElement(d.Z,{item:!0,xs:12,md:11,lg:9},l.createElement(r9.Z,null,l.createElement(sf.Z,{title:"Register Feeds Manager"}),l.createElement(aK.Z,null,l.createElement(xf,{initialValues:Tz,onSubmit:t})))))};function TW(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);nt.version?e:t})},[o]),g=l.useMemo(function(){return Mp(o).sort(function(e,t){return t.version-e.version})},[o]),v=function(e,t,n){switch(e){case"PENDING":return l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"text",color:"secondary",onClick:function(){return b("reject",t)}},"Reject"),m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status&&l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve"),m.id===t&&"DELETED"===n.status&&n.pendingUpdate&&l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("cancel",t)}},"Cancel"),l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs")));case"APPROVED":return l.createElement(l.Fragment,null,l.createElement(ox.default,{variant:"contained",onClick:function(){return b("cancel",t)}},"Cancel"),"DELETED"===n.status&&n.pendingUpdate&&l.createElement(x.default,{color:"error"},"This proposal was deleted. Cancel the spec to delete any running jobs"));case"CANCELLED":if(m.id===t&&"DELETED"!==n.status&&"REVOKED"!==n.status)return l.createElement(ox.default,{variant:"contained",color:"primary",onClick:function(){return b("approve",t)}},"Approve");return null;default:return null}};return l.createElement("div",null,g.map(function(e,n){return l.createElement(mR.Z,{defaultExpanded:0===n,key:n},l.createElement(mj.Z,{expandIcon:l.createElement(gp.Z,null)},l.createElement(x.default,{className:t.versionText},"Version ",e.version),l.createElement(Eu.Z,{label:e.status,color:"APPROVED"===e.status?"primary":"default",variant:"REJECTED"===e.status||"CANCELLED"===e.status?"outlined":"default"}),l.createElement("div",{className:t.proposedAtContainer},l.createElement(x.default,null,"Proposed ",l.createElement(aA,{tooltip:!0},e.createdAt)))),l.createElement(mF.Z,{className:t.expansionPanelDetails},l.createElement("div",{className:t.actions},l.createElement("div",{className:t.editContainer},0===n&&("PENDING"===e.status||"CANCELLED"===e.status)&&"DELETED"!==s.status&&"REVOKED"!==s.status&&l.createElement(ox.default,{variant:"contained",onClick:function(){return p(!0)}},"Edit")),l.createElement("div",{className:t.actionsContainer},v(e.status,e.id,s))),l.createElement(gh,{language:"toml",style:gu,"data-testid":"codeblock"},e.definition)))}),l.createElement(oI,{open:null!=c,title:c?My[c.action].title:"",body:c?My[c.action].body:"",onConfirm:function(){if(c){switch(c.action){case"approve":n(c.id);break;case"cancel":r(c.id);break;case"reject":i(c.id)}f(null)}},cancelButtonText:"Cancel",onCancel:function(){return f(null)}}),l.createElement(Mi,{open:h,onClose:function(){return p(!1)},initialValues:{definition:m.definition,id:m.id},onSubmit:a}))});function M_(e,t){return t||(t=e.slice(0)),Object.freeze(Object.defineProperties(e,{raw:{value:Object.freeze(t)}}))}function ME(){var e=M_(["\n ","\n fragment JobProposalPayloadFields on JobProposal {\n id\n externalJobID\n remoteUUID\n jobID\n specs {\n ...JobProposal_SpecsFields\n }\n status\n pendingUpdate\n }\n"]);return ME=function(){return e},e}var MS=n0(ME(),Mg),Mk=function(e){var t=e.onApprove,n=e.onCancel,r=e.onReject,i=e.onUpdateSpec,a=e.proposal;return l.createElement(iv,null,l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(iw,null,"Job Proposal #",a.id))),l.createElement(T8,{proposal:a}),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:9},l.createElement(TU,null,"Specs"))),l.createElement(d.Z,{container:!0,spacing:32},l.createElement(d.Z,{item:!0,xs:12},l.createElement(Mw,{proposal:a,specs:a.specs,onReject:r,onApprove:t,onCancel:n,onUpdateSpec:i}))))};function Mx(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]e.length)&&(t=e.length);for(var n=0,r=Array(t);ne.length)&&(t=e.length);for(var n=0,r=Array(t);nU,tA:()=>$,KL:()=>H,Iw:()=>V,DQ:()=>W,cB:()=>T,LO:()=>M,t5:()=>k,qt:()=>x,Jc:()=>C,L7:()=>Y,EO:()=>B});var r,i,a=n(66289),o=n(41800),s=n.n(o),u=n(67932);(i=r||(r={})).IN_PROGRESS="in_progress",i.PENDING_INCOMING_CONFIRMATIONS="pending_incoming_confirmations",i.PENDING_CONNECTION="pending_connection",i.PENDING_BRIDGE="pending_bridge",i.PENDING_SLEEP="pending_sleep",i.ERRORED="errored",i.COMPLETED="completed";var c=n(87013),l=n(19084),f=n(34823);function d(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]j,v2:()=>F});var r=n(66289);function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var a="/sessions",o="/sessions",s=function e(t){var n=this;i(this,e),this.api=t,this.createSession=function(e){return n.create(e)},this.destroySession=function(){return n.destroy()},this.create=this.api.createResource(a),this.destroy=this.api.deleteResource(o)};function u(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var c="/v2/bulk_delete_runs",l=function e(t){var n=this;u(this,e),this.api=t,this.bulkDeleteJobRuns=function(e){return n.destroy(e)},this.destroy=this.api.deleteResource(c)};function f(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var d="/v2/chains/evm",h="".concat(d,"/:id"),p=function e(t){var n=this;f(this,e),this.api=t,this.getChains=function(){return n.index()},this.createChain=function(e){return n.create(e)},this.destroyChain=function(e){return n.destroy(void 0,{id:e})},this.updateChain=function(e,t){return n.update(t,{id:e})},this.index=this.api.fetchResource(d),this.create=this.api.createResource(d),this.destroy=this.api.deleteResource(h),this.update=this.api.updateResource(h)};function b(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var m="/v2/keys/evm/chain",g=function e(t){var n=this;b(this,e),this.api=t,this.chain=function(e){var t=new URLSearchParams;t.append("address",e.address),t.append("evmChainID",e.evmChainID),null!==e.nextNonce&&t.append("nextNonce",e.nextNonce),null!==e.abandon&&t.append("abandon",String(e.abandon)),null!==e.enabled&&t.append("enabled",String(e.enabled));var r=m+"?"+t.toString();return n.api.createResource(r)()}};function v(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var y="/v2/jobs",w="".concat(y,"/:specId/runs"),_=function e(t){var n=this;v(this,e),this.api=t,this.createJobRunV2=function(e,t){return n.post(t,{specId:e})},this.post=this.api.createResource(w,!0)};function E(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var S="/v2/log",k=function e(t){var n=this;E(this,e),this.api=t,this.getLogConfig=function(){return n.show()},this.updateLogConfig=function(e){return n.update(e)},this.show=this.api.fetchResource(S),this.update=this.api.updateResource(S)};function x(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var T="/v2/nodes",M=function e(t){var n=this;x(this,e),this.api=t,this.getNodes=function(){return n.index()},this.createNode=function(e){return n.create(e)},this.index=this.api.fetchResource(T),this.create=this.api.createResource(T)};function O(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var A="/v2/enroll_webauthn",L=function e(t){var n=this;O(this,e),this.api=t,this.beginKeyRegistration=function(e){return n.create(e)},this.finishKeyRegistration=function(e){return n.put(e)},this.create=this.api.fetchResource(A),this.put=this.api.createResource(A)};function C(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var I="/v2/build_info",D=function e(t){var n=this;C(this,e),this.api=t,this.show=function(){return n.api.GET(I)()}};function N(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}var P=function e(t){N(this,e),this.api=t,this.buildInfo=new D(this.api),this.bulkDeleteRuns=new l(this.api),this.chains=new p(this.api),this.logConfig=new k(this.api),this.nodes=new M(this.api),this.jobs=new _(this.api),this.webauthn=new L(this.api),this.evmKeys=new g(this.api)},R=new r.V0({base:void 0}),j=new s(R),F=new P(R)},1398(e,t,n){"use strict";n.d(t,{Z:()=>d});var r=n(67294),i=n(32316),a=n(83638),o=n(94184),s=n.n(o);function u(){return(u=Object.assign||function(e){for(var t=1;tc});var r=n(67294),i=n(32316);function a(){return(a=Object.assign||function(e){for(var t=1;tx,jK:()=>v});var r=n(67294),i=n(55977),a=n(45697),o=n.n(a),s=n(82204),u=n(71426),c=n(94184),l=n.n(c),f=n(32316),d=function(e){var t=e.palette.success||{},n=e.palette.warning||{};return{base:{paddingLeft:5*e.spacing.unit,paddingRight:5*e.spacing.unit},success:{backgroundColor:t.main,color:t.contrastText},error:{backgroundColor:e.palette.error.dark,color:e.palette.error.contrastText},warning:{backgroundColor:n.contrastText,color:n.main}}},h=function(e){var t,n=e.success,r=e.error,i=e.warning,a=e.classes,o=e.className;return n?t=a.success:r?t=a.error:i&&(t=a.warning),l()(a.base,o,t)},p=function(e){return r.createElement(s.Z,{className:h(e),square:!0},r.createElement(u.default,{variant:"body2",color:"inherit",component:"div"},e.children))};p.defaultProps={success:!1,error:!1,warning:!1},p.propTypes={success:o().bool,error:o().bool,warning:o().bool};let b=(0,f.withStyles)(d)(p);var m=function(){return r.createElement(r.Fragment,null,"Unhandled error. Please help us by opening a"," ",r.createElement("a",{href:"https://github.com/smartcontractkit/chainlink/issues/new"},"bug report"))};let g=m;function v(e){return"string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null)}function y(e,t){var n;return n="string"==typeof e?e:e.component?e.component(e.props):r.createElement(g,null),r.createElement("p",{key:t},n)}var w=function(e){var t=e.notifications;return r.createElement(b,{error:!0},t.map(y))},_=function(e){var t=e.notifications;return r.createElement(b,{success:!0},t.map(y))},E=function(e){var t=e.errors,n=e.successes;return r.createElement("div",null,(null==t?void 0:t.length)>0&&r.createElement(w,{notifications:t}),n.length>0&&r.createElement(_,{notifications:n}))},S=function(e){return{errors:e.notifications.errors,successes:e.notifications.successes}},k=(0,i.$j)(S)(E);let x=k},9409(e,t,n){"use strict";n.d(t,{ZP:()=>j});var r=n(67294),i=n(55977),a=n(47886),o=n(32316),s=n(1398),u=n(82204),c=n(30060),l=n(71426),f=n(60520),d=n(97779),h=n(57209),p=n(26842),b=n(3950),m=n(5536),g=n(45697),v=n.n(g);let y=n.p+"9f6d832ef97e8493764e.svg";function w(){return(w=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&_.map(function(e,t){return r.createElement(d.Z,{item:!0,xs:12,key:t},r.createElement(u.Z,{raised:!1,className:v.error},r.createElement(c.Z,null,r.createElement(l.default,{variant:"body1",className:v.errorText},(0,b.jK)(e)))))}),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"email",label:"Email",margin:"normal",value:n,onChange:m("email"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(f.Z,{id:"password",label:"Password",type:"password",autoComplete:"password",margin:"normal",value:h,onChange:m("password"),error:_.length>0,variant:"outlined",fullWidth:!0})),r.createElement(d.Z,{item:!0,xs:12},r.createElement(d.Z,{container:!0,spacing:0,justify:"center"},r.createElement(d.Z,{item:!0},r.createElement(s.Z,{type:"submit",variant:"primary"},"Access Account")))),y&&r.createElement(l.default,{variant:"body1",color:"textSecondary"},"Signing in...")))))))},P=function(e){return{fetching:e.authentication.fetching,authenticated:e.authentication.allowed,errors:e.notifications.errors}},R=(0,i.$j)(P,x({submitSignIn:p.L7}))(N);let j=(0,h.wU)(e)((0,o.withStyles)(D)(R))},16353(e,t,n){"use strict";n.d(t,{ZP:()=>H,rH:()=>U});var r,i=n(55977),a=n(15857),o=n(9541),s=n(19084);function u(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function c(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:h,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.Mk.RECEIVE_SIGNOUT_SUCCESS:case s.Mk.RECEIVE_SIGNIN_SUCCESS:var n={allowed:t.authenticated};return o.Ks(n),f(c({},e,n),{errors:[]});case s.Mk.RECEIVE_SIGNIN_FAIL:var r={allowed:!1};return o.Ks(r),f(c({},e,r),{errors:[]});case s.Mk.RECEIVE_SIGNIN_ERROR:case s.Mk.RECEIVE_SIGNOUT_ERROR:var i={allowed:!1};return o.Ks(i),f(c({},e,i),{errors:t.errors||[]});default:return e}};let b=p;function m(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function g(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:_,t=arguments.length>1?arguments[1]:void 0;return t.type?t.type.startsWith(r.REQUEST)?y(g({},e),{count:e.count+1}):t.type.startsWith(r.RECEIVE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type.startsWith(r.RESPONSE)?y(g({},e),{count:Math.max(e.count-1,0)}):t.type===s.di.REDIRECT?y(g({},e),{count:0}):e:e};let S=E;function k(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function x(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:O,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.MATCH_ROUTE:return M(x({},O),{currentUrl:t.pathname});case s.Ih.NOTIFY_SUCCESS:var n={component:t.component,props:t.props};return M(x({},e),{successes:[n],errors:[]});case s.Ih.NOTIFY_SUCCESS_MSG:return M(x({},e),{successes:[t.msg],errors:[]});case s.Ih.NOTIFY_ERROR:var r=t.error.errors,i=null==r?void 0:r.map(function(e){return L(t,e)});return M(x({},e),{successes:[],errors:i});case s.Ih.NOTIFY_ERROR_MSG:return M(x({},e),{successes:[],errors:[t.msg]});case s.Mk.RECEIVE_SIGNIN_FAIL:return M(x({},e),{successes:[],errors:["Your email or password is incorrect. Please try again"]});default:return e}};function L(e,t){return{component:e.component,props:{msg:t.detail}}}let C=A;function I(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function D(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:R,t=arguments.length>1?arguments[1]:void 0;switch(t.type){case s.di.REDIRECT:return P(D({},e),{to:t.to});case s.di.MATCH_ROUTE:return P(D({},e),{to:void 0});default:return e}};let F=j;var Y=n(87013),B=(0,a.UY)({authentication:b,fetching:S,notifications:C,redirect:F,buildInfo:Y.Z});B(void 0,{type:"INITIAL_STATE"});var U=i.v9;let H=B},19084(e,t,n){"use strict";var r,i,a,o,s,u,c,l,f,d;n.d(t,{Ih:()=>i,Mk:()=>a,Y0:()=>s,di:()=>r,jp:()=>o}),n(67294),(u=r||(r={})).REDIRECT="REDIRECT",u.MATCH_ROUTE="MATCH_ROUTE",(c=i||(i={})).NOTIFY_SUCCESS="NOTIFY_SUCCESS",c.NOTIFY_SUCCESS_MSG="NOTIFY_SUCCESS_MSG",c.NOTIFY_ERROR="NOTIFY_ERROR",c.NOTIFY_ERROR_MSG="NOTIFY_ERROR_MSG",(l=a||(a={})).REQUEST_SIGNIN="REQUEST_SIGNIN",l.RECEIVE_SIGNIN_SUCCESS="RECEIVE_SIGNIN_SUCCESS",l.RECEIVE_SIGNIN_FAIL="RECEIVE_SIGNIN_FAIL",l.RECEIVE_SIGNIN_ERROR="RECEIVE_SIGNIN_ERROR",l.RECEIVE_SIGNOUT_SUCCESS="RECEIVE_SIGNOUT_SUCCESS",l.RECEIVE_SIGNOUT_ERROR="RECEIVE_SIGNOUT_ERROR",(f=o||(o={})).RECEIVE_CREATE_ERROR="RECEIVE_CREATE_ERROR",f.RECEIVE_CREATE_SUCCESS="RECEIVE_CREATE_SUCCESS",f.RECEIVE_DELETE_ERROR="RECEIVE_DELETE_ERROR",f.RECEIVE_DELETE_SUCCESS="RECEIVE_DELETE_SUCCESS",f.RECEIVE_UPDATE_ERROR="RECEIVE_UPDATE_ERROR",f.RECEIVE_UPDATE_SUCCESS="RECEIVE_UPDATE_SUCCESS",f.REQUEST_CREATE="REQUEST_CREATE",f.REQUEST_DELETE="REQUEST_DELETE",f.REQUEST_UPDATE="REQUEST_UPDATE",f.UPSERT_CONFIGURATION="UPSERT_CONFIGURATION",f.UPSERT_JOB_RUN="UPSERT_JOB_RUN",f.UPSERT_JOB_RUNS="UPSERT_JOB_RUNS",f.UPSERT_TRANSACTION="UPSERT_TRANSACTION",f.UPSERT_TRANSACTIONS="UPSERT_TRANSACTIONS",f.UPSERT_BUILD_INFO="UPSERT_BUILD_INFO",(d=s||(s={})).FETCH_BUILD_INFO_REQUESTED="FETCH_BUILD_INFO_REQUESTED",d.FETCH_BUILD_INFO_SUCCEEDED="FETCH_BUILD_INFO_SUCCEEDED",d.FETCH_BUILD_INFO_FAILED="FETCH_BUILD_INFO_FAILED"},87013(e,t,n){"use strict";n.d(t,{Y:()=>o,Z:()=>u});var r=n(19084);function i(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e){for(var t=1;t0&&void 0!==arguments[0]?arguments[0]:o,t=arguments.length>1?arguments[1]:void 0;return t.type===r.Y0.FETCH_BUILD_INFO_SUCCEEDED?a({},t.buildInfo):e};let u=s},34823(e,t,n){"use strict";n.d(t,{N:()=>r});var r=function(e){return e.buildInfo}},73343(e,t,n){"use strict";n.d(t,{r:()=>u});var r=n(19350),i=n(32316),a=n(59114),o=n(5324),s={props:{MuiGrid:{spacing:3*o.default.unit},MuiCardHeader:{titleTypographyProps:{color:"secondary"}}},palette:{action:{hoverOpacity:.3},primary:{light:"#E5F1FF",main:"#3c40c6",contrastText:"#fff"},secondary:{main:"#3d5170"},success:{light:"#e8faf1",main:r.ek.A700,dark:r.ek[700],contrastText:r.y0.white},warning:{light:"#FFFBF1",main:"#fff6b6",contrastText:"#fad27a"},error:{light:"#ffdada",main:"#f44336",dark:"#d32f2f",contrastText:"#fff"},background:{default:"#f5f6f8",appBar:"#3c40c6"},text:{primary:(0,a.darken)(r.BA.A700,.7),secondary:"#818ea3"},listPendingStatus:{background:"#fef7e5",color:"#fecb4c"},listCompletedStatus:{background:"#e9faf2",color:"#4ed495"}},shape:{borderRadius:o.default.unit},overrides:{MuiButton:{root:{borderRadius:o.default.unit/2,textTransform:"none"},sizeLarge:{padding:void 0,fontSize:void 0,paddingTop:o.default.unit,paddingBottom:o.default.unit,paddingLeft:5*o.default.unit,paddingRight:5*o.default.unit}},MuiTableCell:{body:{fontSize:"1rem"},head:{fontSize:"1rem",fontWeight:400}},MuiCardHeader:{root:{borderBottom:"1px solid rgba(0, 0, 0, 0.12)"},action:{marginTop:-2,marginRight:0,"& >*":{marginLeft:2*o.default.unit}},subheader:{marginTop:.5*o.default.unit}}},typography:{useNextVariants:!0,fontFamily:"-apple-system,BlinkMacSystemFont,Roboto,Helvetica,Arial,sans-serif",button:{textTransform:"none",fontSize:"1.2em"},body1:{fontSize:"1.0rem",fontWeight:400,lineHeight:"1.46429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body2:{fontSize:"1.0rem",fontWeight:500,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},body1Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"1rem",lineHeight:1.5,letterSpacing:-.4},body2Next:{color:"rgb(29, 29, 29)",fontWeight:400,fontSize:"0.875rem",lineHeight:1.5,letterSpacing:-.4},display1:{color:"#818ea3",fontSize:"2.125rem",fontWeight:400,lineHeight:"1.20588em",letterSpacing:-.4},display2:{color:"#818ea3",fontSize:"2.8125rem",fontWeight:400,lineHeight:"1.13333em",marginLeft:"-.02em",letterSpacing:-.4},display3:{color:"#818ea3",fontSize:"3.5rem",fontWeight:400,lineHeight:"1.30357em",marginLeft:"-.02em",letterSpacing:-.4},display4:{fontSize:14,fontWeightLight:300,fontWeightMedium:500,fontWeightRegular:400,letterSpacing:-.4},h1:{color:"rgb(29, 29, 29)",fontSize:"6rem",fontWeight:300,lineHeight:1},h2:{color:"rgb(29, 29, 29)",fontSize:"3.75rem",fontWeight:300,lineHeight:1},h3:{color:"rgb(29, 29, 29)",fontSize:"3rem",fontWeight:400,lineHeight:1.04},h4:{color:"rgb(29, 29, 29)",fontSize:"2.125rem",fontWeight:400,lineHeight:1.17},h5:{color:"rgb(29, 29, 29)",fontSize:"1.5rem",fontWeight:400,lineHeight:1.33,letterSpacing:-.4},h6:{fontSize:"0.8rem",fontWeight:450,lineHeight:"1.71429em",color:"rgba(0, 0, 0, 0.87)",letterSpacing:-.4},subheading:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:"1.5em",letterSpacing:-.4},subtitle1:{color:"rgb(29, 29, 29)",fontSize:"1rem",fontWeight:400,lineHeight:1.75,letterSpacing:-.4},subtitle2:{color:"rgb(29, 29, 29)",fontSize:"0.875rem",fontWeight:500,lineHeight:1.57,letterSpacing:-.4}},shadows:["none","0px 1px 3px 0px rgba(0, 0, 0, 0.1),0px 1px 1px 0px rgba(0, 0, 0, 0.04),0px 2px 1px -1px rgba(0, 0, 0, 0.02)","0px 1px 5px 0px rgba(0, 0, 0, 0.1),0px 2px 2px 0px rgba(0, 0, 0, 0.04),0px 3px 1px -2px rgba(0, 0, 0, 0.02)","0px 1px 8px 0px rgba(0, 0, 0, 0.1),0px 3px 4px 0px rgba(0, 0, 0, 0.04),0px 3px 3px -2px rgba(0, 0, 0, 0.02)","0px 2px 4px -1px rgba(0, 0, 0, 0.1),0px 4px 5px 0px rgba(0, 0, 0, 0.04),0px 1px 10px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 5px 8px 0px rgba(0, 0, 0, 0.04),0px 1px 14px 0px rgba(0, 0, 0, 0.02)","0px 3px 5px -1px rgba(0, 0, 0, 0.1),0px 6px 10px 0px rgba(0, 0, 0, 0.04),0px 1px 18px 0px rgba(0, 0, 0, 0.02)","0px 4px 5px -2px rgba(0, 0, 0, 0.1),0px 7px 10px 1px rgba(0, 0, 0, 0.04),0px 2px 16px 1px rgba(0, 0, 0, 0.02)","0px 5px 5px -3px rgba(0, 0, 0, 0.1),0px 8px 10px 1px rgba(0, 0, 0, 0.04),0px 3px 14px 2px rgba(0, 0, 0, 0.02)","0px 5px 6px -3px rgba(0, 0, 0, 0.1),0px 9px 12px 1px rgba(0, 0, 0, 0.04),0px 3px 16px 2px rgba(0, 0, 0, 0.02)","0px 6px 6px -3px rgba(0, 0, 0, 0.1),0px 10px 14px 1px rgba(0, 0, 0, 0.04),0px 4px 18px 3px rgba(0, 0, 0, 0.02)","0px 6px 7px -4px rgba(0, 0, 0, 0.1),0px 11px 15px 1px rgba(0, 0, 0, 0.04),0px 4px 20px 3px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 12px 17px 2px rgba(0, 0, 0, 0.04),0px 5px 22px 4px rgba(0, 0, 0, 0.02)","0px 7px 8px -4px rgba(0, 0, 0, 0.1),0px 13px 19px 2px rgba(0, 0, 0, 0.04),0px 5px 24px 4px rgba(0, 0, 0, 0.02)","0px 7px 9px -4px rgba(0, 0, 0, 0.1),0px 14px 21px 2px rgba(0, 0, 0, 0.04),0px 5px 26px 4px rgba(0, 0, 0, 0.02)","0px 8px 9px -5px rgba(0, 0, 0, 0.1),0px 15px 22px 2px rgba(0, 0, 0, 0.04),0px 6px 28px 5px rgba(0, 0, 0, 0.02)","0px 8px 10px -5px rgba(0, 0, 0, 0.1),0px 16px 24px 2px rgba(0, 0, 0, 0.04),0px 6px 30px 5px rgba(0, 0, 0, 0.02)","0px 8px 11px -5px rgba(0, 0, 0, 0.1),0px 17px 26px 2px rgba(0, 0, 0, 0.04),0px 6px 32px 5px rgba(0, 0, 0, 0.02)","0px 9px 11px -5px rgba(0, 0, 0, 0.1),0px 18px 28px 2px rgba(0, 0, 0, 0.04),0px 7px 34px 6px rgba(0, 0, 0, 0.02)","0px 9px 12px -6px rgba(0, 0, 0, 0.1),0px 19px 29px 2px rgba(0, 0, 0, 0.04),0px 7px 36px 6px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 20px 31px 3px rgba(0, 0, 0, 0.04),0px 8px 38px 7px rgba(0, 0, 0, 0.02)","0px 10px 13px -6px rgba(0, 0, 0, 0.1),0px 21px 33px 3px rgba(0, 0, 0, 0.04),0px 8px 40px 7px rgba(0, 0, 0, 0.02)","0px 10px 14px -6px rgba(0, 0, 0, 0.1),0px 22px 35px 3px rgba(0, 0, 0, 0.04),0px 8px 42px 7px rgba(0, 0, 0, 0.02)","0px 11px 14px -7px rgba(0, 0, 0, 0.1),0px 23px 36px 3px rgba(0, 0, 0, 0.04),0px 9px 44px 8px rgba(0, 0, 0, 0.02)","0px 11px 15px -7px rgba(0, 0, 0, 0.1),0px 24px 38px 3px rgba(0, 0, 0, 0.04),0px 9px 46px 8px rgba(0, 0, 0, 0.02)",]},u=(0,i.createMuiTheme)(s)},66289(e,t,n){"use strict";function r(e){if(void 0===e)throw ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function i(e,t){if(!(e instanceof t))throw TypeError("Cannot call a class as a function")}function a(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(e){return!1}}function o(e,t,n){return(o=a()?Reflect.construct:function(e,t,n){var r=[null];r.push.apply(r,t);var i=new(Function.bind.apply(e,r));return n&&f(i,n.prototype),i}).apply(null,arguments)}function s(e){return(s=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)})(e)}function u(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),t&&f(e,t)}function c(e){return -1!==Function.toString.call(e).indexOf("[native code]")}function l(e,t){return t&&("object"===p(t)||"function"==typeof t)?t:r(e)}function f(e,t){return(f=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e})(e,t)}n.d(t,{V0:()=>B,_7:()=>v});var d,h,p=function(e){return e&&"undefined"!=typeof Symbol&&e.constructor===Symbol?"symbol":typeof e};function b(e){var t="function"==typeof Map?new Map:void 0;return(b=function(e){if(null===e||!c(e))return e;if("function"!=typeof e)throw TypeError("Super expression must either be null or a function");if(void 0!==t){if(t.has(e))return t.get(e);t.set(e,n)}function n(){return o(e,arguments,s(this).constructor)}return n.prototype=Object.create(e.prototype,{constructor:{value:n,enumerable:!1,writable:!0,configurable:!0}}),f(n,e)})(e)}function m(){if("undefined"==typeof Reflect||!Reflect.construct||Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],function(){})),!0}catch(e){return!1}}function g(e){var t=m();return function(){var n,r=s(e);if(t){var i=s(this).constructor;n=Reflect.construct(r,arguments,i)}else n=r.apply(this,arguments);return l(this,n)}}var v=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"AuthenticationError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e},],r}return n}(b(Error)),y=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"BadRequestError")).errors=a,r}return n}(b(Error)),w=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnprocessableEntityError")).errors=e,r}return n}(b(Error)),_=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"ServerError")).errors=e,r}return n}(b(Error)),E=function(e){u(n,e);var t=g(n);function n(e){var r,a=e.errors;return i(this,n),(r=t.call(this,"ConflictError")).errors=a,r}return n}(b(Error)),S=function(e){u(n,e);var t=g(n);function n(e){var r;return i(this,n),(r=t.call(this,"UnknownResponseError(".concat(e.statusText,")"))).errors=[{status:e.status,detail:e.statusText},],r}return n}(b(Error));function k(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:2e4;return Promise.race([fetch(e,t),new Promise(function(e,t){return setTimeout(function(){return t(Error("timeout"))},n)}),])}function x(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n0&&i[i.length-1])&&(6===a[0]||2===a[0])){o=0;continue}if(3===a[0]&&(!i||a[1]>i[0]&&a[1]=200&&e.status<300))return[3,2];return[2,e.json()];case 2:if(400!==e.status)return[3,3];return[2,e.json().then(function(e){throw new y(e)})];case 3:if(401!==e.status)return[3,4];throw new v(e);case 4:if(422!==e.status)return[3,6];return[4,$(e)];case 5:throw n=i.sent(),new w(n);case 6:if(409!==e.status)return[3,7];return[2,e.json().then(function(e){throw new E(e)})];case 7:if(!(e.status>=500))return[3,9];return[4,$(e)];case 8:throw r=i.sent(),new _(r);case 9:throw new S(e);case 10:return[2]}})})).apply(this,arguments)}function $(e){return z.apply(this,arguments)}function z(){return(z=j(function(e){return Y(this,function(t){return[2,e.json().then(function(t){return t.errors?t.errors.map(function(t){return{status:e.status,detail:t.detail}}):G(e)}).catch(function(){return G(e)})]})})).apply(this,arguments)}function G(e){return[{status:e.status,detail:e.statusText},]}},50109(e,t,n){"use strict";n.d(t,{LK:()=>o,U2:()=>i,eT:()=>s,t8:()=>a});var r=n(12795);function i(e){return r.ZP.getItem("chainlink.".concat(e))}function a(e,t){r.ZP.setItem("chainlink.".concat(e),t)}function o(e){var t=i(e),n={};if(t)try{return JSON.parse(t)}catch(r){}return n}function s(e,t){a(e,JSON.stringify(t))}},9541(e,t,n){"use strict";n.d(t,{Ks:()=>u,Tp:()=>a,iR:()=>o,pm:()=>s});var r=n(50109),i="persistURL";function a(){return r.U2(i)||""}function o(e){r.t8(i,e)}function s(){return r.LK("authentication")}function u(e){r.eT("authentication",e)}},67121(e,t,n){"use strict";function r(e){var t,n=e.Symbol;return"function"==typeof n?n.observable?t=n.observable:(t=n("observable"),n.observable=t):t="@@observable",t}n.r(t),n.d(t,{default:()=>o}),e=n.hmd(e),i="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n.g?n.g:e;var i,a=r(i);let o=a},2177(e,t,n){"use strict";n.d(t,{Z:()=>o});var r=!0,i="Invariant failed";function a(e,t){if(!e){if(r)throw Error(i);throw Error(i+": "+(t||""))}}let o=a},11742(e){e.exports=function(){var e=document.getSelection();if(!e.rangeCount)return function(){};for(var t=document.activeElement,n=[],r=0;ri,pi:()=>a});var r=function(e,t){return(r=Object.setPrototypeOf||({__proto__:[]})instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})(e,t)};function i(e,t){if("function"!=typeof t&&null!==t)throw TypeError("Class extends value "+String(t)+" is not a constructor or null");function n(){this.constructor=e}r(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}var a=function(){return(a=Object.assign||function(e){for(var t,n=1,r=arguments.length;nr})},94927(e,t,n){function r(e,t){if(i("noDeprecation"))return e;var n=!1;function r(){if(!n){if(i("throwDeprecation"))throw Error(t);i("traceDeprecation")?console.trace(t):console.warn(t),n=!0}return e.apply(this,arguments)}return r}function i(e){try{if(!n.g.localStorage)return!1}catch(t){return!1}var r=n.g.localStorage[e];return null!=r&&"true"===String(r).toLowerCase()}e.exports=r},42473(e){"use strict";var t=function(){};e.exports=t},84763(e){e.exports=Worker},47529(e){e.exports=n;var t=Object.prototype.hasOwnProperty;function n(){for(var e={},n=0;nr,O:()=>a}),(i=r||(r={}))[i.loading=1]="loading",i[i.setVariables=2]="setVariables",i[i.fetchMore=3]="fetchMore",i[i.refetch=4]="refetch",i[i.poll=6]="poll",i[i.ready=7]="ready",i[i.error=8]="error"},30990(e,t,n){"use strict";n.d(t,{MS:()=>s,YG:()=>a,cA:()=>c,ls:()=>o});var r=n(23564);n(83952);var i=n(13154),a=Symbol();function o(e){return!!e.extensions&&Array.isArray(e.extensions[a])}function s(e){return e.hasOwnProperty("graphQLErrors")}var u=function(e){var t=(0,r.ev)((0,r.ev)((0,r.ev)([],e.graphQLErrors,!0),e.clientErrors,!0),e.protocolErrors,!0);return e.networkError&&t.push(e.networkError),t.map(function(e){return(0,i.s)(e)&&e.message||"Error message not found."}).join("\n")},c=function(e){function t(n){var r=n.graphQLErrors,i=n.protocolErrors,a=n.clientErrors,o=n.networkError,s=n.errorMessage,c=n.extraInfo,l=e.call(this,s)||this;return l.name="ApolloError",l.graphQLErrors=r||[],l.protocolErrors=i||[],l.clientErrors=a||[],l.networkError=o||null,l.message=s||u(l),l.extraInfo=c,l.__proto__=t.prototype,l}return(0,r.ZT)(t,e),t}(Error)},85317(e,t,n){"use strict";n.d(t,{K:()=>a});var r=n(67294),i=n(30320).aS?Symbol.for("__APOLLO_CONTEXT__"):"__APOLLO_CONTEXT__";function a(){var e=r.createContext[i];return e||(Object.defineProperty(r.createContext,i,{value:e=r.createContext({}),enumerable:!1,writable:!1,configurable:!0}),e.displayName="ApolloContext"),e}},21436(e,t,n){"use strict";n.d(t,{O:()=>i,k:()=>r});var r=Array.isArray;function i(e){return Array.isArray(e)&&e.length>0}},30320(e,t,n){"use strict";n.d(t,{DN:()=>s,JC:()=>l,aS:()=>o,mr:()=>i,sy:()=>a});var r=n(83952),i="function"==typeof WeakMap&&"ReactNative"!==(0,r.wY)(function(){return navigator.product}),a="function"==typeof WeakSet,o="function"==typeof Symbol&&"function"==typeof Symbol.for,s=o&&Symbol.asyncIterator,u="function"==typeof(0,r.wY)(function(){return window.document.createElement}),c=(0,r.wY)(function(){return navigator.userAgent.indexOf("jsdom")>=0})||!1,l=u&&!c},53712(e,t,n){"use strict";function r(){for(var e=[],t=0;tr})},10542(e,t,n){"use strict";n.d(t,{J:()=>o}),n(83952);var r=n(13154);function i(e){var t=new Set([e]);return t.forEach(function(e){(0,r.s)(e)&&a(e)===e&&Object.getOwnPropertyNames(e).forEach(function(n){(0,r.s)(e[n])&&t.add(e[n])})}),e}function a(e){if(__DEV__&&!Object.isFrozen(e))try{Object.freeze(e)}catch(t){if(t instanceof TypeError)return null;throw t}return e}function o(e){return __DEV__&&i(e),e}},14012(e,t,n){"use strict";n.d(t,{J:()=>a});var r=n(23564),i=n(53712);function a(e,t){return(0,i.o)(e,t,t.variables&&{variables:(0,r.pi)((0,r.pi)({},e&&e.variables),t.variables)})}},13154(e,t,n){"use strict";function r(e){return null!==e&&"object"==typeof e}n.d(t,{s:()=>r})},83952(e,t,n){"use strict";n.d(t,{ej:()=>u,kG:()=>c,wY:()=>h});var r,i=n(70655),a="Invariant Violation",o=Object.setPrototypeOf,s=void 0===o?function(e,t){return e.__proto__=t,e}:o,u=function(e){function t(n){void 0===n&&(n=a);var r=e.call(this,"number"==typeof n?a+": "+n+" (see https://github.com/apollographql/invariant-packages)":n)||this;return r.framesToPop=1,r.name=a,s(r,t.prototype),r}return(0,i.ZT)(t,e),t}(Error);function c(e,t){if(!e)throw new u(t)}var l=["debug","log","warn","error","silent"],f=l.indexOf("log");function d(e){return function(){if(l.indexOf(e)>=f)return(console[e]||console.log).apply(console,arguments)}}function h(e){try{return e()}catch(t){}}(r=c||(c={})).debug=d("debug"),r.log=d("log"),r.warn=d("warn"),r.error=d("error");let p=h(function(){return globalThis})||h(function(){return window})||h(function(){return self})||h(function(){return global})||h(function(){return h.constructor("return this")()});var b="__",m=[b,b].join("DEV");function g(){try{return Boolean(__DEV__)}catch(e){return Object.defineProperty(p,m,{value:"production"!==h(function(){return"production"}),enumerable:!1,configurable:!0,writable:!0}),p[m]}}let v=g();function y(e){try{return e()}catch(t){}}var w=y(function(){return globalThis})||y(function(){return window})||y(function(){return self})||y(function(){return global})||y(function(){return y.constructor("return this")()}),_=!1;function E(){!w||y(function(){return"production"})||y(function(){return process})||(Object.defineProperty(w,"process",{value:{env:{NODE_ENV:"production"}},configurable:!0,enumerable:!1,writable:!0}),_=!0)}function S(){_&&(delete w.process,_=!1)}E();var k=n(10143);function x(){return k.H,S()}function T(){__DEV__?c("boolean"==typeof v,v):c("boolean"==typeof v,39)}x(),T()},87462(e,t,n){"use strict";function r(){return(r=Object.assign||function(e){for(var t=1;tr})},25821(e,t,n){"use strict";n.d(t,{Z:()=>s});var r=n(45695);function i(e){return(i="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}var a=10,o=2;function s(e){return u(e,[])}function u(e,t){switch(i(e)){case"string":return JSON.stringify(e);case"function":return e.name?"[function ".concat(e.name,"]"):"[function]";case"object":if(null===e)return"null";return c(e,t);default:return String(e)}}function c(e,t){if(-1!==t.indexOf(e))return"[Circular]";var n=[].concat(t,[e]),r=d(e);if(void 0!==r){var i=r.call(e);if(i!==e)return"string"==typeof i?i:u(i,n)}else if(Array.isArray(e))return f(e,n);return l(e,n)}function l(e,t){var n=Object.keys(e);return 0===n.length?"{}":t.length>o?"["+h(e)+"]":"{ "+n.map(function(n){var r=u(e[n],t);return n+": "+r}).join(", ")+" }"}function f(e,t){if(0===e.length)return"[]";if(t.length>o)return"[Array]";for(var n=Math.min(a,e.length),r=e.length-n,i=[],s=0;s1&&i.push("... ".concat(r," more items")),"["+i.join(", ")+"]"}function d(e){var t=e[String(r.Z)];return"function"==typeof t?t:"function"==typeof e.inspect?e.inspect:void 0}function h(e){var t=Object.prototype.toString.call(e).replace(/^\[object /,"").replace(/]$/,"");if("Object"===t&&"function"==typeof e.constructor){var n=e.constructor.name;if("string"==typeof n&&""!==n)return n}return t}},45695(e,t,n){"use strict";n.d(t,{Z:()=>i});var r="function"==typeof Symbol&&"function"==typeof Symbol.for?Symbol.for("nodejs.util.inspect.custom"):void 0;let i=r},25217(e,t,n){"use strict";function r(e,t){if(!Boolean(e))throw Error(null!=t?t:"Unexpected invariant triggered.")}n.d(t,{Ye:()=>o,WU:()=>s,UG:()=>u});var i=n(45695);function a(e){var t=e.prototype.toJSON;"function"==typeof t||r(0),e.prototype.inspect=t,i.Z&&(e.prototype[i.Z]=t)}var o=function(){function e(e,t,n){this.start=e.start,this.end=t.end,this.startToken=e,this.endToken=t,this.source=n}return e.prototype.toJSON=function(){return{start:this.start,end:this.end}},e}();a(o);var s=function(){function e(e,t,n,r,i,a,o){this.kind=e,this.start=t,this.end=n,this.line=r,this.column=i,this.value=o,this.prev=a,this.next=null}return e.prototype.toJSON=function(){return{kind:this.kind,value:this.value,line:this.line,column:this.column}},e}();function u(e){return null!=e&&"string"==typeof e.kind}a(s)},87392(e,t,n){"use strict";function r(e){var t=e.split(/\r\n|[\n\r]/g),n=a(e);if(0!==n)for(var r=1;ro&&i(t[s-1]);)--s;return t.slice(o,s).join("\n")}function i(e){for(var t=0;t1&&void 0!==arguments[1]?arguments[1]:"",n=arguments.length>2&&void 0!==arguments[2]&&arguments[2],r=-1===e.indexOf("\n"),i=" "===e[0]||" "===e[0],a='"'===e[e.length-1],o="\\"===e[e.length-1],s=!r||a||o||n,u="";return s&&!(r&&i)&&(u+="\n"+t),u+=t?e.replace(/\n/g,"\n"+t):e,s&&(u+="\n"),'"""'+u.replace(/"""/g,'\\"""')+'"""'}n.d(t,{LZ:()=>o,W7:()=>r})},97359(e,t,n){"use strict";n.d(t,{h:()=>r});var r=Object.freeze({NAME:"Name",DOCUMENT:"Document",OPERATION_DEFINITION:"OperationDefinition",VARIABLE_DEFINITION:"VariableDefinition",SELECTION_SET:"SelectionSet",FIELD:"Field",ARGUMENT:"Argument",FRAGMENT_SPREAD:"FragmentSpread",INLINE_FRAGMENT:"InlineFragment",FRAGMENT_DEFINITION:"FragmentDefinition",VARIABLE:"Variable",INT:"IntValue",FLOAT:"FloatValue",STRING:"StringValue",BOOLEAN:"BooleanValue",NULL:"NullValue",ENUM:"EnumValue",LIST:"ListValue",OBJECT:"ObjectValue",OBJECT_FIELD:"ObjectField",DIRECTIVE:"Directive",NAMED_TYPE:"NamedType",LIST_TYPE:"ListType",NON_NULL_TYPE:"NonNullType",SCHEMA_DEFINITION:"SchemaDefinition",OPERATION_TYPE_DEFINITION:"OperationTypeDefinition",SCALAR_TYPE_DEFINITION:"ScalarTypeDefinition",OBJECT_TYPE_DEFINITION:"ObjectTypeDefinition",FIELD_DEFINITION:"FieldDefinition",INPUT_VALUE_DEFINITION:"InputValueDefinition",INTERFACE_TYPE_DEFINITION:"InterfaceTypeDefinition",UNION_TYPE_DEFINITION:"UnionTypeDefinition",ENUM_TYPE_DEFINITION:"EnumTypeDefinition",ENUM_VALUE_DEFINITION:"EnumValueDefinition",INPUT_OBJECT_TYPE_DEFINITION:"InputObjectTypeDefinition",DIRECTIVE_DEFINITION:"DirectiveDefinition",SCHEMA_EXTENSION:"SchemaExtension",SCALAR_TYPE_EXTENSION:"ScalarTypeExtension",OBJECT_TYPE_EXTENSION:"ObjectTypeExtension",INTERFACE_TYPE_EXTENSION:"InterfaceTypeExtension",UNION_TYPE_EXTENSION:"UnionTypeExtension",ENUM_TYPE_EXTENSION:"EnumTypeExtension",INPUT_OBJECT_TYPE_EXTENSION:"InputObjectTypeExtension"})},10143(e,t,n){"use strict";n.d(t,{H:()=>c,T:()=>l});var r=n(99763),i=n(25821);function a(e,t){if(!Boolean(e))throw Error(t)}let o=function(e,t){return e instanceof t};function s(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:"GraphQL request",n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{line:1,column:1};"string"==typeof e||a(0,"Body must be a string. Received: ".concat((0,i.Z)(e),".")),this.body=e,this.name=t,this.locationOffset=n,this.locationOffset.line>0||a(0,"line in locationOffset is 1-indexed and must be positive."),this.locationOffset.column>0||a(0,"column in locationOffset is 1-indexed and must be positive.")}return u(e,[{key:r.YF,get:function(){return"Source"}}]),e}();function l(e){return o(e,c)}},99763(e,t,n){"use strict";n.d(t,{YF:()=>r});var r="function"==typeof Symbol&&null!=Symbol.toStringTag?Symbol.toStringTag:"@@toStringTag"},37452(e){"use strict";e.exports=JSON.parse('{"AElig":"\xc6","AMP":"&","Aacute":"\xc1","Acirc":"\xc2","Agrave":"\xc0","Aring":"\xc5","Atilde":"\xc3","Auml":"\xc4","COPY":"\xa9","Ccedil":"\xc7","ETH":"\xd0","Eacute":"\xc9","Ecirc":"\xca","Egrave":"\xc8","Euml":"\xcb","GT":">","Iacute":"\xcd","Icirc":"\xce","Igrave":"\xcc","Iuml":"\xcf","LT":"<","Ntilde":"\xd1","Oacute":"\xd3","Ocirc":"\xd4","Ograve":"\xd2","Oslash":"\xd8","Otilde":"\xd5","Ouml":"\xd6","QUOT":"\\"","REG":"\xae","THORN":"\xde","Uacute":"\xda","Ucirc":"\xdb","Ugrave":"\xd9","Uuml":"\xdc","Yacute":"\xdd","aacute":"\xe1","acirc":"\xe2","acute":"\xb4","aelig":"\xe6","agrave":"\xe0","amp":"&","aring":"\xe5","atilde":"\xe3","auml":"\xe4","brvbar":"\xa6","ccedil":"\xe7","cedil":"\xb8","cent":"\xa2","copy":"\xa9","curren":"\xa4","deg":"\xb0","divide":"\xf7","eacute":"\xe9","ecirc":"\xea","egrave":"\xe8","eth":"\xf0","euml":"\xeb","frac12":"\xbd","frac14":"\xbc","frac34":"\xbe","gt":">","iacute":"\xed","icirc":"\xee","iexcl":"\xa1","igrave":"\xec","iquest":"\xbf","iuml":"\xef","laquo":"\xab","lt":"<","macr":"\xaf","micro":"\xb5","middot":"\xb7","nbsp":"\xa0","not":"\xac","ntilde":"\xf1","oacute":"\xf3","ocirc":"\xf4","ograve":"\xf2","ordf":"\xaa","ordm":"\xba","oslash":"\xf8","otilde":"\xf5","ouml":"\xf6","para":"\xb6","plusmn":"\xb1","pound":"\xa3","quot":"\\"","raquo":"\xbb","reg":"\xae","sect":"\xa7","shy":"\xad","sup1":"\xb9","sup2":"\xb2","sup3":"\xb3","szlig":"\xdf","thorn":"\xfe","times":"\xd7","uacute":"\xfa","ucirc":"\xfb","ugrave":"\xf9","uml":"\xa8","uuml":"\xfc","yacute":"\xfd","yen":"\xa5","yuml":"\xff"}')},93580(e){"use strict";e.exports=JSON.parse('{"0":"�","128":"€","130":"‚","131":"ƒ","132":"„","133":"…","134":"†","135":"‡","136":"ˆ","137":"‰","138":"Š","139":"‹","140":"Œ","142":"Ž","145":"‘","146":"’","147":"“","148":"”","149":"•","150":"–","151":"—","152":"˜","153":"™","154":"š","155":"›","156":"œ","158":"ž","159":"Ÿ"}')},67946(e){"use strict";e.exports=JSON.parse('{"locale":"en","long":{"year":{"previous":"last year","current":"this year","next":"next year","past":{"one":"{0} year ago","other":"{0} years ago"},"future":{"one":"in {0} year","other":"in {0} years"}},"quarter":{"previous":"last quarter","current":"this quarter","next":"next quarter","past":{"one":"{0} quarter ago","other":"{0} quarters ago"},"future":{"one":"in {0} quarter","other":"in {0} quarters"}},"month":{"previous":"last month","current":"this month","next":"next month","past":{"one":"{0} month ago","other":"{0} months ago"},"future":{"one":"in {0} month","other":"in {0} months"}},"week":{"previous":"last week","current":"this week","next":"next week","past":{"one":"{0} week ago","other":"{0} weeks ago"},"future":{"one":"in {0} week","other":"in {0} weeks"}},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":{"one":"{0} hour ago","other":"{0} hours ago"},"future":{"one":"in {0} hour","other":"in {0} hours"}},"minute":{"current":"this minute","past":{"one":"{0} minute ago","other":"{0} minutes ago"},"future":{"one":"in {0} minute","other":"in {0} minutes"}},"second":{"current":"now","past":{"one":"{0} second ago","other":"{0} seconds ago"},"future":{"one":"in {0} second","other":"in {0} seconds"}}},"short":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"narrow":{"year":{"previous":"last yr.","current":"this yr.","next":"next yr.","past":"{0} yr. ago","future":"in {0} yr."},"quarter":{"previous":"last qtr.","current":"this qtr.","next":"next qtr.","past":{"one":"{0} qtr. ago","other":"{0} qtrs. ago"},"future":{"one":"in {0} qtr.","other":"in {0} qtrs."}},"month":{"previous":"last mo.","current":"this mo.","next":"next mo.","past":"{0} mo. ago","future":"in {0} mo."},"week":{"previous":"last wk.","current":"this wk.","next":"next wk.","past":"{0} wk. ago","future":"in {0} wk."},"day":{"previous":"yesterday","current":"today","next":"tomorrow","past":{"one":"{0} day ago","other":"{0} days ago"},"future":{"one":"in {0} day","other":"in {0} days"}},"hour":{"current":"this hour","past":"{0} hr. ago","future":"in {0} hr."},"minute":{"current":"this minute","past":"{0} min. ago","future":"in {0} min."},"second":{"current":"now","past":"{0} sec. ago","future":"in {0} sec."}},"now":{"now":{"current":"now","future":"in a moment","past":"just now"}},"mini":{"year":"{0}yr","month":"{0}mo","week":"{0}wk","day":"{0}d","hour":"{0}h","minute":"{0}m","second":"{0}s","now":"now"},"short-time":{"year":"{0} yr.","month":"{0} mo.","week":"{0} wk.","day":{"one":"{0} day","other":"{0} days"},"hour":"{0} hr.","minute":"{0} min.","second":"{0} sec."},"long-time":{"year":{"one":"{0} year","other":"{0} years"},"month":{"one":"{0} month","other":"{0} months"},"week":{"one":"{0} week","other":"{0} weeks"},"day":{"one":"{0} day","other":"{0} days"},"hour":{"one":"{0} hour","other":"{0} hours"},"minute":{"one":"{0} minute","other":"{0} minutes"},"second":{"one":"{0} second","other":"{0} seconds"}}}')}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={id:e,loaded:!1,exports:{}};return __webpack_modules__[e].call(n.exports,n,n.exports,__webpack_require__),n.loaded=!0,n.exports}__webpack_require__.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return __webpack_require__.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;__webpack_require__.t=function(n,r){if(1&r&&(n=this(n)),8&r||"object"==typeof n&&n&&(4&r&&n.__esModule||16&r&&"function"==typeof n.then))return n;var i=Object.create(null);__webpack_require__.r(i);var a={};e=e||[null,t({}),t([]),t(t)];for(var o=2&r&&n;"object"==typeof o&&!~e.indexOf(o);o=t(o))Object.getOwnPropertyNames(o).forEach(e=>a[e]=()=>n[e]);return a.default=()=>n,__webpack_require__.d(i,a),i}})(),__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),__webpack_require__.hmd=e=>((e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set(){throw Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e),__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},__webpack_require__.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),__webpack_require__.p="/assets/",__webpack_require__.nc=void 0;var __webpack_exports__={};(()=>{"use strict";var e,t,n,r,i=__webpack_require__(32316),a=__webpack_require__(8126),o=__webpack_require__(5690),s=__webpack_require__(30381),u=__webpack_require__.n(s),c=__webpack_require__(67294),l=__webpack_require__(73935),f=__webpack_require__.n(l),d=__webpack_require__(57209),h=__webpack_require__(55977),p=__webpack_require__(15857),b=__webpack_require__(28500);function m(e){return function(t){var n=t.dispatch,r=t.getState;return function(t){return function(i){return"function"==typeof i?i(n,r,e):t(i)}}}}var g=m();g.withExtraArgument=m;let v=g;var y=__webpack_require__(76489);function w(e){return function(t){return function(n){return function(r){n(r);var i=e||document&&document.cookie||"",a=t.getState();if("MATCH_ROUTE"===r.type&&"/signin"!==a.notifications.currentUrl){var o=(0,y.Q)(i);if(o.explorer)try{var s=JSON.parse(o.explorer);if("error"===s.status){var u=_(s.url);n({type:"NOTIFY_ERROR_MSG",msg:u})}}catch(c){n({type:"NOTIFY_ERROR_MSG",msg:"Invalid explorer status"})}}}}}}function _(e){var t="Can't connect to explorer: ".concat(e);return e.match(/^wss?:.+/)?t:"".concat(t,". You must use a websocket.")}var E=__webpack_require__(16353);function S(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n=e.length?{done:!0}:{done:!1,value:e[r++]}}}throw TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function ei(e,t){if(e){if("string"==typeof e)return ea(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);if("Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n)return Array.from(e);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return ea(e,t)}}function ea(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=Array(t);n1,i=!1,a=arguments[1],o=a;return new n(function(n){return t.subscribe({next:function(t){var a=!i;if(i=!0,!a||r)try{o=e(o,t)}catch(s){return n.error(s)}else o=t},error:function(e){n.error(e)},complete:function(){if(!i&&!r)return n.error(TypeError("Cannot reduce an empty sequence"));n.next(o),n.complete()}})})},t.concat=function(){for(var e=this,t=arguments.length,n=Array(t),r=0;r=0&&i.splice(e,1),o()}});i.push(s)},error:function(e){r.error(e)},complete:function(){o()}});function o(){a.closed&&0===i.length&&r.complete()}return function(){i.forEach(function(e){return e.unsubscribe()}),a.unsubscribe()}})},t[ed]=function(){return this},e.from=function(t){var n="function"==typeof this?this:e;if(null==t)throw TypeError(t+" is not an object");var r=ep(t,ed);if(r){var i=r.call(t);if(Object(i)!==i)throw TypeError(i+" is not an object");return em(i)&&i.constructor===n?i:new n(function(e){return i.subscribe(e)})}if(ec("iterator")&&(r=ep(t,ef)))return new n(function(e){ev(function(){if(!e.closed){for(var n,i=er(r.call(t));!(n=i()).done;){var a=n.value;if(e.next(a),e.closed)return}e.complete()}})});if(Array.isArray(t))return new n(function(e){ev(function(){if(!e.closed){for(var n=0;n0))return n.connection.key;var r=n.connection.filter?n.connection.filter:[];r.sort();var i={};return r.forEach(function(e){i[e]=t[e]}),"".concat(n.connection.key,"(").concat(eV(i),")")}var a=e;if(t){var o=eV(t);a+="(".concat(o,")")}return n&&Object.keys(n).forEach(function(e){-1===eW.indexOf(e)&&(n[e]&&Object.keys(n[e]).length?a+="@".concat(e,"(").concat(eV(n[e]),")"):a+="@".concat(e))}),a},{setStringify:function(e){var t=eV;return eV=e,t}}),eV=function(e){return JSON.stringify(e,eq)};function eq(e,t){return(0,eO.s)(t)&&!Array.isArray(t)&&(t=Object.keys(t).sort().reduce(function(e,n){return e[n]=t[n],e},{})),t}function eZ(e,t){if(e.arguments&&e.arguments.length){var n={};return e.arguments.forEach(function(e){var r;return ez(n,e.name,e.value,t)}),n}return null}function eX(e){return e.alias?e.alias.value:e.name.value}function eJ(e,t,n){for(var r,i=0,a=t.selections;it.indexOf(i))throw __DEV__?new Q.ej("illegal argument: ".concat(i)):new Q.ej(27)}return e}function tt(e,t){return t?t(e):eT.of()}function tn(e){return"function"==typeof e?new ta(e):e}function tr(e){return e.request.length<=1}var ti=function(e){function t(t,n){var r=e.call(this,t)||this;return r.link=n,r}return(0,en.ZT)(t,e),t}(Error),ta=function(){function e(e){e&&(this.request=e)}return e.empty=function(){return new e(function(){return eT.of()})},e.from=function(t){return 0===t.length?e.empty():t.map(tn).reduce(function(e,t){return e.concat(t)})},e.split=function(t,n,r){var i=tn(n),a=tn(r||new e(tt));return new e(tr(i)&&tr(a)?function(e){return t(e)?i.request(e)||eT.of():a.request(e)||eT.of()}:function(e,n){return t(e)?i.request(e,n)||eT.of():a.request(e,n)||eT.of()})},e.execute=function(e,t){return e.request(eM(t.context,e7(te(t))))||eT.of()},e.concat=function(t,n){var r=tn(t);if(tr(r))return __DEV__&&Q.kG.warn(new ti("You are calling concat on a terminating link, which will have no effect",r)),r;var i=tn(n);return new e(tr(i)?function(e){return r.request(e,function(e){return i.request(e)||eT.of()})||eT.of()}:function(e,t){return r.request(e,function(e){return i.request(e,t)||eT.of()})||eT.of()})},e.prototype.split=function(t,n,r){return this.concat(e.split(t,n,r||new e(tt)))},e.prototype.concat=function(t){return e.concat(this,t)},e.prototype.request=function(e,t){throw __DEV__?new Q.ej("request is not implemented"):new Q.ej(22)},e.prototype.onError=function(e,t){if(t&&t.error)return t.error(e),!1;throw e},e.prototype.setOnError=function(e){return this.onError=e,this},e}(),to=__webpack_require__(25821),ts=__webpack_require__(25217),tu={Name:[],Document:["definitions"],OperationDefinition:["name","variableDefinitions","directives","selectionSet"],VariableDefinition:["variable","type","defaultValue","directives"],Variable:["name"],SelectionSet:["selections"],Field:["alias","name","arguments","directives","selectionSet"],Argument:["name","value"],FragmentSpread:["name","directives"],InlineFragment:["typeCondition","directives","selectionSet"],FragmentDefinition:["name","variableDefinitions","typeCondition","directives","selectionSet"],IntValue:[],FloatValue:[],StringValue:[],BooleanValue:[],NullValue:[],EnumValue:[],ListValue:["values"],ObjectValue:["fields"],ObjectField:["name","value"],Directive:["name","arguments"],NamedType:["name"],ListType:["type"],NonNullType:["type"],SchemaDefinition:["description","directives","operationTypes"],OperationTypeDefinition:["type"],ScalarTypeDefinition:["description","name","directives"],ObjectTypeDefinition:["description","name","interfaces","directives","fields"],FieldDefinition:["description","name","arguments","type","directives"],InputValueDefinition:["description","name","type","defaultValue","directives"],InterfaceTypeDefinition:["description","name","interfaces","directives","fields"],UnionTypeDefinition:["description","name","directives","types"],EnumTypeDefinition:["description","name","directives","values"],EnumValueDefinition:["description","name","directives"],InputObjectTypeDefinition:["description","name","directives","fields"],DirectiveDefinition:["description","name","arguments","locations"],SchemaExtension:["directives","operationTypes"],ScalarTypeExtension:["name","directives"],ObjectTypeExtension:["name","interfaces","directives","fields"],InterfaceTypeExtension:["name","interfaces","directives","fields"],UnionTypeExtension:["name","directives","types"],EnumTypeExtension:["name","directives","values"],InputObjectTypeExtension:["name","directives","fields"]},tc=Object.freeze({});function tl(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:tu,r=void 0,i=Array.isArray(e),a=[e],o=-1,s=[],u=void 0,c=void 0,l=void 0,f=[],d=[],h=e;do{var p,b=++o===a.length,m=b&&0!==s.length;if(b){if(c=0===d.length?void 0:f[f.length-1],u=l,l=d.pop(),m){if(i)u=u.slice();else{for(var g={},v=0,y=Object.keys(u);v1)for(var r=new tB,i=1;i=0;--a){var o=i[a],s=isNaN(+o)?{}:[];s[o]=t,t=s}n=r.merge(n,t)}),n}var tW=Object.prototype.hasOwnProperty;function tK(e,t){var n,r,i,a,o;return(0,en.mG)(this,void 0,void 0,function(){var s,u,c,l,f,d,h,p,b,m,g,v,y,w,_,E,S,k,x,T,M,O,A;return(0,en.Jh)(this,function(L){switch(L.label){case 0:if(void 0===TextDecoder)throw Error("TextDecoder must be defined in the environment: please import a polyfill.");s=new TextDecoder("utf-8"),u=null===(n=e.headers)||void 0===n?void 0:n.get("content-type"),c="boundary=",l=(null==u?void 0:u.includes(c))?null==u?void 0:u.substring((null==u?void 0:u.indexOf(c))+c.length).replace(/['"]/g,"").replace(/\;(.*)/gm,"").trim():"-",f="\r\n--".concat(l),d="",h=tI(e),p=!0,L.label=1;case 1:if(!p)return[3,3];return[4,h.next()];case 2:for(m=(b=L.sent()).value,g=b.done,v="string"==typeof m?m:s.decode(m),y=d.length-f.length+1,p=!g,d+=v,w=d.indexOf(f,y);w>-1;){if(_=void 0,_=(O=[d.slice(0,w),d.slice(w+f.length),])[0],d=O[1],E=_.indexOf("\r\n\r\n"),(k=(S=tV(_.slice(0,E)))["content-type"])&&-1===k.toLowerCase().indexOf("application/json"))throw Error("Unsupported patch content type: application/json is required.");if(x=_.slice(E))try{T=tq(e,x),Object.keys(T).length>1||"data"in T||"incremental"in T||"errors"in T||"payload"in T?tz(T)?(M={},"payload"in T&&(M=(0,en.pi)({},T.payload)),"errors"in T&&(M=(0,en.pi)((0,en.pi)({},M),{extensions:(0,en.pi)((0,en.pi)({},"extensions"in M?M.extensions:null),((A={})[tN.YG]=T.errors,A))})),null===(r=t.next)||void 0===r||r.call(t,M)):null===(i=t.next)||void 0===i||i.call(t,T):1===Object.keys(T).length&&"hasNext"in T&&!T.hasNext&&(null===(a=t.complete)||void 0===a||a.call(t))}catch(C){tZ(C,t)}w=d.indexOf(f)}return[3,1];case 3:return null===(o=t.complete)||void 0===o||o.call(t),[2]}})})}function tV(e){var t={};return e.split("\n").forEach(function(e){var n=e.indexOf(":");if(n>-1){var r=e.slice(0,n).trim().toLowerCase(),i=e.slice(n+1).trim();t[r]=i}}),t}function tq(e,t){e.status>=300&&tD(e,function(){try{return JSON.parse(t)}catch(e){return t}}(),"Response not successful: Received status code ".concat(e.status));try{return JSON.parse(t)}catch(n){var r=n;throw r.name="ServerParseError",r.response=e,r.statusCode=e.status,r.bodyText=t,r}}function tZ(e,t){var n,r;"AbortError"!==e.name&&(e.result&&e.result.errors&&e.result.data&&(null===(n=t.next)||void 0===n||n.call(t,e.result)),null===(r=t.error)||void 0===r||r.call(t,e))}function tX(e,t,n){tJ(t)(e).then(function(e){var t,r;null===(t=n.next)||void 0===t||t.call(n,e),null===(r=n.complete)||void 0===r||r.call(n)}).catch(function(e){return tZ(e,n)})}function tJ(e){return function(t){return t.text().then(function(e){return tq(t,e)}).then(function(n){return t.status>=300&&tD(t,n,"Response not successful: Received status code ".concat(t.status)),Array.isArray(n)||tW.call(n,"data")||tW.call(n,"errors")||tD(t,n,"Server response was missing for query '".concat(Array.isArray(e)?e.map(function(e){return e.operationName}):e.operationName,"'.")),n})}}var tQ=function(e){if(!e&&"undefined"==typeof fetch)throw __DEV__?new Q.ej("\n\"fetch\" has not been found globally and no fetcher has been configured. To fix this, install a fetch package (like https://www.npmjs.com/package/cross-fetch), instantiate the fetcher, and pass it into your HttpLink constructor. For example:\n\nimport fetch from 'cross-fetch';\nimport { ApolloClient, HttpLink } from '@apollo/client';\nconst client = new ApolloClient({\n link: new HttpLink({ uri: '/graphql', fetch })\n});\n "):new Q.ej(23)},t1=__webpack_require__(87392);function t0(e){return tl(e,{leave:t3})}var t2=80,t3={Name:function(e){return e.value},Variable:function(e){return"$"+e.name},Document:function(e){return t5(e.definitions,"\n\n")+"\n"},OperationDefinition:function(e){var t=e.operation,n=e.name,r=t9("(",t5(e.variableDefinitions,", "),")"),i=t5(e.directives," "),a=e.selectionSet;return n||i||r||"query"!==t?t5([t,t5([n,r]),i,a]," "):a},VariableDefinition:function(e){var t=e.variable,n=e.type,r=e.defaultValue,i=e.directives;return t+": "+n+t9(" = ",r)+t9(" ",t5(i," "))},SelectionSet:function(e){return t6(e.selections)},Field:function(e){var t=e.alias,n=e.name,r=e.arguments,i=e.directives,a=e.selectionSet,o=t9("",t,": ")+n,s=o+t9("(",t5(r,", "),")");return s.length>t2&&(s=o+t9("(\n",t8(t5(r,"\n")),"\n)")),t5([s,t5(i," "),a]," ")},Argument:function(e){var t;return e.name+": "+e.value},FragmentSpread:function(e){var t;return"..."+e.name+t9(" ",t5(e.directives," "))},InlineFragment:function(e){var t=e.typeCondition,n=e.directives,r=e.selectionSet;return t5(["...",t9("on ",t),t5(n," "),r]," ")},FragmentDefinition:function(e){var t=e.name,n=e.typeCondition,r=e.variableDefinitions,i=e.directives,a=e.selectionSet;return"fragment ".concat(t).concat(t9("(",t5(r,", "),")")," ")+"on ".concat(n," ").concat(t9("",t5(i," ")," "))+a},IntValue:function(e){return e.value},FloatValue:function(e){return e.value},StringValue:function(e,t){var n=e.value;return e.block?(0,t1.LZ)(n,"description"===t?"":" "):JSON.stringify(n)},BooleanValue:function(e){return e.value?"true":"false"},NullValue:function(){return"null"},EnumValue:function(e){return e.value},ListValue:function(e){return"["+t5(e.values,", ")+"]"},ObjectValue:function(e){return"{"+t5(e.fields,", ")+"}"},ObjectField:function(e){var t;return e.name+": "+e.value},Directive:function(e){var t;return"@"+e.name+t9("(",t5(e.arguments,", "),")")},NamedType:function(e){return e.name},ListType:function(e){return"["+e.type+"]"},NonNullType:function(e){return e.type+"!"},SchemaDefinition:t4(function(e){var t=e.directives,n=e.operationTypes;return t5(["schema",t5(t," "),t6(n)]," ")}),OperationTypeDefinition:function(e){var t;return e.operation+": "+e.type},ScalarTypeDefinition:t4(function(e){var t;return t5(["scalar",e.name,t5(e.directives," ")]," ")}),ObjectTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["type",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")}),FieldDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.type,i=e.directives;return t+(ne(n)?t9("(\n",t8(t5(n,"\n")),"\n)"):t9("(",t5(n,", "),")"))+": "+r+t9(" ",t5(i," "))}),InputValueDefinition:t4(function(e){var t=e.name,n=e.type,r=e.defaultValue,i=e.directives;return t5([t+": "+n,t9("= ",r),t5(i," ")]," ")}),InterfaceTypeDefinition:t4(function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["interface",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")}),UnionTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.types;return t5(["union",t,t5(n," "),r&&0!==r.length?"= "+t5(r," | "):""]," ")}),EnumTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.values;return t5(["enum",t,t5(n," "),t6(r)]," ")}),EnumValueDefinition:t4(function(e){var t;return t5([e.name,t5(e.directives," ")]," ")}),InputObjectTypeDefinition:t4(function(e){var t=e.name,n=e.directives,r=e.fields;return t5(["input",t,t5(n," "),t6(r)]," ")}),DirectiveDefinition:t4(function(e){var t=e.name,n=e.arguments,r=e.repeatable,i=e.locations;return"directive @"+t+(ne(n)?t9("(\n",t8(t5(n,"\n")),"\n)"):t9("(",t5(n,", "),")"))+(r?" repeatable":"")+" on "+t5(i," | ")}),SchemaExtension:function(e){var t=e.directives,n=e.operationTypes;return t5(["extend schema",t5(t," "),t6(n)]," ")},ScalarTypeExtension:function(e){var t;return t5(["extend scalar",e.name,t5(e.directives," ")]," ")},ObjectTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["extend type",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")},InterfaceTypeExtension:function(e){var t=e.name,n=e.interfaces,r=e.directives,i=e.fields;return t5(["extend interface",t,t9("implements ",t5(n," & ")),t5(r," "),t6(i)]," ")},UnionTypeExtension:function(e){var t=e.name,n=e.directives,r=e.types;return t5(["extend union",t,t5(n," "),r&&0!==r.length?"= "+t5(r," | "):""]," ")},EnumTypeExtension:function(e){var t=e.name,n=e.directives,r=e.values;return t5(["extend enum",t,t5(n," "),t6(r)]," ")},InputObjectTypeExtension:function(e){var t=e.name,n=e.directives,r=e.fields;return t5(["extend input",t,t5(n," "),t6(r)]," ")}};function t4(e){return function(t){return t5([t.description,e(t)],"\n")}}function t5(e){var t,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"";return null!==(t=null==e?void 0:e.filter(function(e){return e}).join(n))&&void 0!==t?t:""}function t6(e){return t9("{\n",t8(t5(e,"\n")),"\n}")}function t9(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"";return null!=t&&""!==t?e+t+n:""}function t8(e){return t9(" ",e.replace(/\n/g,"\n "))}function t7(e){return -1!==e.indexOf("\n")}function ne(e){return null!=e&&e.some(t7)}var nt,nn,nr,ni={http:{includeQuery:!0,includeExtensions:!1,preserveHeaderCase:!1},headers:{accept:"*/*","content-type":"application/json"},options:{method:"POST"}},na=function(e,t){return t(e)};function no(e,t){for(var n=[],r=2;rObject.create(null),{forEach:nv,slice:ny}=Array.prototype,{hasOwnProperty:nw}=Object.prototype;class n_{constructor(e=!0,t=ng){this.weakness=e,this.makeData=t}lookup(...e){return this.lookupArray(e)}lookupArray(e){let t=this;return nv.call(e,e=>t=t.getChildTrie(e)),nw.call(t,"data")?t.data:t.data=this.makeData(ny.call(e))}peek(...e){return this.peekArray(e)}peekArray(e){let t=this;for(let n=0,r=e.length;t&&n=0;--o)t.definitions[o].kind===nL.h.OPERATION_DEFINITION&&++a;var s=nN(e),u=e.some(function(e){return e.remove}),c=function(e){return u&&e&&e.some(s)},l=new Map,f=!1,d={enter:function(e){if(c(e.directives))return f=!0,null}},h=tl(t,{Field:d,InlineFragment:d,VariableDefinition:{enter:function(){return!1}},Variable:{enter:function(e,t,n,r,a){var o=i(a);o&&o.variables.add(e.name.value)}},FragmentSpread:{enter:function(e,t,n,r,a){if(c(e.directives))return f=!0,null;var o=i(a);o&&o.fragmentSpreads.add(e.name.value)}},FragmentDefinition:{enter:function(e,t,n,r){l.set(JSON.stringify(r),e)},leave:function(e,t,n,i){return e===l.get(JSON.stringify(i))?e:a>0&&e.selectionSet.selections.every(function(e){return e.kind===nL.h.FIELD&&"__typename"===e.name.value})?(r(e.name.value).removed=!0,f=!0,null):void 0}},Directive:{leave:function(e){if(s(e))return f=!0,null}}});if(!f)return t;var p=function(e){return e.transitiveVars||(e.transitiveVars=new Set(e.variables),e.removed||e.fragmentSpreads.forEach(function(t){p(r(t)).transitiveVars.forEach(function(t){e.transitiveVars.add(t)})})),e},b=new Set;h.definitions.forEach(function(e){e.kind===nL.h.OPERATION_DEFINITION?p(n(e.name&&e.name.value)).fragmentSpreads.forEach(function(e){b.add(e)}):e.kind!==nL.h.FRAGMENT_DEFINITION||0!==a||r(e.name.value).removed||b.add(e.name.value)}),b.forEach(function(e){p(r(e)).fragmentSpreads.forEach(function(e){b.add(e)})});var m=function(e){return!!(!b.has(e)||r(e).removed)},g={enter:function(e){if(m(e.name.value))return null}};return nD(tl(h,{FragmentSpread:g,FragmentDefinition:g,OperationDefinition:{leave:function(e){if(e.variableDefinitions){var t=p(n(e.name&&e.name.value)).transitiveVars;if(t.size0},t.prototype.tearDownQuery=function(){this.isTornDown||(this.concast&&this.observer&&(this.concast.removeObserver(this.observer),delete this.concast,delete this.observer),this.stopPolling(),this.subscriptions.forEach(function(e){return e.unsubscribe()}),this.subscriptions.clear(),this.queryManager.stopQuery(this.queryId),this.observers.clear(),this.isTornDown=!0)},t}(eT);function n4(e){var t=e.options,n=t.fetchPolicy,r=t.nextFetchPolicy;return"cache-and-network"===n||"network-only"===n?e.reobserve({fetchPolicy:"cache-first",nextFetchPolicy:function(){return(this.nextFetchPolicy=r,"function"==typeof r)?r.apply(this,arguments):n}}):e.reobserve()}function n5(e){__DEV__&&Q.kG.error("Unhandled error",e.message,e.stack)}function n6(e){__DEV__&&e&&__DEV__&&Q.kG.debug("Missing cache result fields: ".concat(JSON.stringify(e)),e)}function n9(e){return"network-only"===e||"no-cache"===e||"standby"===e}nK(n3);function n8(e){return e.kind===nL.h.FIELD||e.kind===nL.h.FRAGMENT_SPREAD||e.kind===nL.h.INLINE_FRAGMENT}function n7(e){return e.kind===Kind.SCALAR_TYPE_DEFINITION||e.kind===Kind.OBJECT_TYPE_DEFINITION||e.kind===Kind.INTERFACE_TYPE_DEFINITION||e.kind===Kind.UNION_TYPE_DEFINITION||e.kind===Kind.ENUM_TYPE_DEFINITION||e.kind===Kind.INPUT_OBJECT_TYPE_DEFINITION}function re(e){return e.kind===Kind.SCALAR_TYPE_EXTENSION||e.kind===Kind.OBJECT_TYPE_EXTENSION||e.kind===Kind.INTERFACE_TYPE_EXTENSION||e.kind===Kind.UNION_TYPE_EXTENSION||e.kind===Kind.ENUM_TYPE_EXTENSION||e.kind===Kind.INPUT_OBJECT_TYPE_EXTENSION}var rt=function(){return Object.create(null)},rn=Array.prototype,rr=rn.forEach,ri=rn.slice,ra=function(){function e(e,t){void 0===e&&(e=!0),void 0===t&&(t=rt),this.weakness=e,this.makeData=t}return e.prototype.lookup=function(){for(var e=[],t=0;tclass{constructor(){this.id=["slot",rc++,Date.now(),Math.random().toString(36).slice(2),].join(":")}hasValue(){for(let e=rs;e;e=e.parent)if(this.id in e.slots){let t=e.slots[this.id];if(t===ru)break;return e!==rs&&(rs.slots[this.id]=t),!0}return rs&&(rs.slots[this.id]=ru),!1}getValue(){if(this.hasValue())return rs.slots[this.id]}withValue(e,t,n,r){let i={__proto__:null,[this.id]:e},a=rs;rs={parent:a,slots:i};try{return t.apply(r,n)}finally{rs=a}}static bind(e){let t=rs;return function(){let n=rs;try{return rs=t,e.apply(this,arguments)}finally{rs=n}}}static noContext(e,t,n){if(!rs)return e.apply(n,t);{let r=rs;try{return rs=null,e.apply(n,t)}finally{rs=r}}}};function rf(e){try{return e()}catch(t){}}let rd="@wry/context:Slot",rh=rf(()=>globalThis)||rf(()=>global)||Object.create(null),rp=rh,rb=rp[rd]||Array[rd]||function(e){try{Object.defineProperty(rp,rd,{value:e,enumerable:!1,writable:!1,configurable:!0})}finally{return e}}(rl()),{bind:rm,noContext:rg}=rb;function rv(){}var ry=function(){function e(e,t){void 0===e&&(e=1/0),void 0===t&&(t=rv),this.max=e,this.dispose=t,this.map=new Map,this.newest=null,this.oldest=null}return e.prototype.has=function(e){return this.map.has(e)},e.prototype.get=function(e){var t=this.getNode(e);return t&&t.value},e.prototype.getNode=function(e){var t=this.map.get(e);if(t&&t!==this.newest){var n=t.older,r=t.newer;r&&(r.older=n),n&&(n.newer=r),t.older=this.newest,t.older.newer=t,t.newer=null,this.newest=t,t===this.oldest&&(this.oldest=r)}return t},e.prototype.set=function(e,t){var n=this.getNode(e);return n?n.value=t:(n={key:e,value:t,newer:null,older:this.newest},this.newest&&(this.newest.newer=n),this.newest=n,this.oldest=this.oldest||n,this.map.set(e,n),n.value)},e.prototype.clean=function(){for(;this.oldest&&this.map.size>this.max;)this.delete(this.oldest.key)},e.prototype.delete=function(e){var t=this.map.get(e);return!!t&&(t===this.newest&&(this.newest=t.older),t===this.oldest&&(this.oldest=t.newer),t.newer&&(t.newer.older=t.older),t.older&&(t.older.newer=t.newer),this.map.delete(e),this.dispose(t.value,e),!0)},e}(),rw=new rb,r_=Object.prototype.hasOwnProperty,rE=void 0===(n=Array.from)?function(e){var t=[];return e.forEach(function(e){return t.push(e)}),t}:n;function rS(e){var t=e.unsubscribe;"function"==typeof t&&(e.unsubscribe=void 0,t())}var rk=[],rx=100;function rT(e,t){if(!e)throw Error(t||"assertion failure")}function rM(e,t){var n=e.length;return n>0&&n===t.length&&e[n-1]===t[n-1]}function rO(e){switch(e.length){case 0:throw Error("unknown value");case 1:return e[0];case 2:throw e[1]}}function rA(e){return e.slice(0)}var rL=function(){function e(t){this.fn=t,this.parents=new Set,this.childValues=new Map,this.dirtyChildren=null,this.dirty=!0,this.recomputing=!1,this.value=[],this.deps=null,++e.count}return e.prototype.peek=function(){if(1===this.value.length&&!rN(this))return rC(this),this.value[0]},e.prototype.recompute=function(e){return rT(!this.recomputing,"already recomputing"),rC(this),rN(this)?rI(this,e):rO(this.value)},e.prototype.setDirty=function(){this.dirty||(this.dirty=!0,this.value.length=0,rR(this),rS(this))},e.prototype.dispose=function(){var e=this;this.setDirty(),rH(this),rF(this,function(t,n){t.setDirty(),r$(t,e)})},e.prototype.forget=function(){this.dispose()},e.prototype.dependOn=function(e){e.add(this),this.deps||(this.deps=rk.pop()||new Set),this.deps.add(e)},e.prototype.forgetDeps=function(){var e=this;this.deps&&(rE(this.deps).forEach(function(t){return t.delete(e)}),this.deps.clear(),rk.push(this.deps),this.deps=null)},e.count=0,e}();function rC(e){var t=rw.getValue();if(t)return e.parents.add(t),t.childValues.has(e)||t.childValues.set(e,[]),rN(e)?rY(t,e):rB(t,e),t}function rI(e,t){return rH(e),rw.withValue(e,rD,[e,t]),rz(e,t)&&rP(e),rO(e.value)}function rD(e,t){e.recomputing=!0,e.value.length=0;try{e.value[0]=e.fn.apply(null,t)}catch(n){e.value[1]=n}e.recomputing=!1}function rN(e){return e.dirty||!!(e.dirtyChildren&&e.dirtyChildren.size)}function rP(e){e.dirty=!1,!rN(e)&&rj(e)}function rR(e){rF(e,rY)}function rj(e){rF(e,rB)}function rF(e,t){var n=e.parents.size;if(n)for(var r=rE(e.parents),i=0;i0&&e.childValues.forEach(function(t,n){r$(e,n)}),e.forgetDeps(),rT(null===e.dirtyChildren)}function r$(e,t){t.parents.delete(e),e.childValues.delete(t),rU(e,t)}function rz(e,t){if("function"==typeof e.subscribe)try{rS(e),e.unsubscribe=e.subscribe.apply(null,t)}catch(n){return e.setDirty(),!1}return!0}var rG={setDirty:!0,dispose:!0,forget:!0};function rW(e){var t=new Map,n=e&&e.subscribe;function r(e){var r=rw.getValue();if(r){var i=t.get(e);i||t.set(e,i=new Set),r.dependOn(i),"function"==typeof n&&(rS(i),i.unsubscribe=n(e))}}return r.dirty=function(e,n){var r=t.get(e);if(r){var i=n&&r_.call(rG,n)?n:"setDirty";rE(r).forEach(function(e){return e[i]()}),t.delete(e),rS(r)}},r}function rK(){var e=new ra("function"==typeof WeakMap);return function(){return e.lookupArray(arguments)}}var rV=rK(),rq=new Set;function rZ(e,t){void 0===t&&(t=Object.create(null));var n=new ry(t.max||65536,function(e){return e.dispose()}),r=t.keyArgs,i=t.makeCacheKey||rK(),a=function(){var a=i.apply(null,r?r.apply(null,arguments):arguments);if(void 0===a)return e.apply(null,arguments);var o=n.get(a);o||(n.set(a,o=new rL(e)),o.subscribe=t.subscribe,o.forget=function(){return n.delete(a)});var s=o.recompute(Array.prototype.slice.call(arguments));return n.set(a,o),rq.add(n),rw.hasValue()||(rq.forEach(function(e){return e.clean()}),rq.clear()),s};function o(e){var t=n.get(e);t&&t.setDirty()}function s(e){var t=n.get(e);if(t)return t.peek()}function u(e){return n.delete(e)}return Object.defineProperty(a,"size",{get:function(){return n.map.size},configurable:!1,enumerable:!1}),a.dirtyKey=o,a.dirty=function(){o(i.apply(null,arguments))},a.peekKey=s,a.peek=function(){return s(i.apply(null,arguments))},a.forgetKey=u,a.forget=function(){return u(i.apply(null,arguments))},a.makeCacheKey=i,a.getKey=r?function(){return i.apply(null,r.apply(null,arguments))}:i,Object.freeze(a)}var rX=new rb,rJ=new WeakMap;function rQ(e){var t=rJ.get(e);return t||rJ.set(e,t={vars:new Set,dep:rW()}),t}function r1(e){rQ(e).vars.forEach(function(t){return t.forgetCache(e)})}function r0(e){rQ(e).vars.forEach(function(t){return t.attachCache(e)})}function r2(e){var t=new Set,n=new Set,r=function(a){if(arguments.length>0){if(e!==a){e=a,t.forEach(function(e){rQ(e).dep.dirty(r),r3(e)});var o=Array.from(n);n.clear(),o.forEach(function(t){return t(e)})}}else{var s=rX.getValue();s&&(i(s),rQ(s).dep(r))}return e};r.onNextChange=function(e){return n.add(e),function(){n.delete(e)}};var i=r.attachCache=function(e){return t.add(e),rQ(e).vars.add(r),r};return r.forgetCache=function(e){return t.delete(e)},r}function r3(e){e.broadcastWatches&&e.broadcastWatches()}var r4=function(){function e(e){var t=e.cache,n=e.client,r=e.resolvers,i=e.fragmentMatcher;this.selectionsToResolveCache=new WeakMap,this.cache=t,n&&(this.client=n),r&&this.addResolvers(r),i&&this.setFragmentMatcher(i)}return e.prototype.addResolvers=function(e){var t=this;this.resolvers=this.resolvers||{},Array.isArray(e)?e.forEach(function(e){t.resolvers=tj(t.resolvers,e)}):this.resolvers=tj(this.resolvers,e)},e.prototype.setResolvers=function(e){this.resolvers={},this.addResolvers(e)},e.prototype.getResolvers=function(){return this.resolvers||{}},e.prototype.runResolvers=function(e){var t=e.document,n=e.remoteResult,r=e.context,i=e.variables,a=e.onlyRunForcedResolvers,o=void 0!==a&&a;return(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(e){return t?[2,this.resolveDocument(t,n.data,r,i,this.fragmentMatcher,o).then(function(e){return(0,en.pi)((0,en.pi)({},n),{data:e.result})})]:[2,n]})})},e.prototype.setFragmentMatcher=function(e){this.fragmentMatcher=e},e.prototype.getFragmentMatcher=function(){return this.fragmentMatcher},e.prototype.clientQuery=function(e){return tb(["client"],e)&&this.resolvers?e:null},e.prototype.serverQuery=function(e){return n$(e)},e.prototype.prepareContext=function(e){var t=this.cache;return(0,en.pi)((0,en.pi)({},e),{cache:t,getCacheKey:function(e){return t.identify(e)}})},e.prototype.addExportedVariables=function(e,t,n){return void 0===t&&(t={}),void 0===n&&(n={}),(0,en.mG)(this,void 0,void 0,function(){return(0,en.Jh)(this,function(r){return e?[2,this.resolveDocument(e,this.buildRootValueFromCache(e,t)||{},this.prepareContext(n),t).then(function(e){return(0,en.pi)((0,en.pi)({},t),e.exportedVariables)})]:[2,(0,en.pi)({},t)]})})},e.prototype.shouldForceResolvers=function(e){var t=!1;return tl(e,{Directive:{enter:function(e){if("client"===e.name.value&&e.arguments&&(t=e.arguments.some(function(e){return"always"===e.name.value&&"BooleanValue"===e.value.kind&&!0===e.value.value})))return tc}}}),t},e.prototype.buildRootValueFromCache=function(e,t){return this.cache.diff({query:nH(e),variables:t,returnPartialData:!0,optimistic:!1}).result},e.prototype.resolveDocument=function(e,t,n,r,i,a){return void 0===n&&(n={}),void 0===r&&(r={}),void 0===i&&(i=function(){return!0}),void 0===a&&(a=!1),(0,en.mG)(this,void 0,void 0,function(){var o,s,u,c,l,f,d,h,p,b,m;return(0,en.Jh)(this,function(g){return o=e9(e),s=e4(e),u=eL(s),c=this.collectSelectionsToResolve(o,u),f=(l=o.operation)?l.charAt(0).toUpperCase()+l.slice(1):"Query",d=this,h=d.cache,p=d.client,b={fragmentMap:u,context:(0,en.pi)((0,en.pi)({},n),{cache:h,client:p}),variables:r,fragmentMatcher:i,defaultOperationType:f,exportedVariables:{},selectionsToResolve:c,onlyRunForcedResolvers:a},m=!1,[2,this.resolveSelectionSet(o.selectionSet,m,t,b).then(function(e){return{result:e,exportedVariables:b.exportedVariables}})]})})},e.prototype.resolveSelectionSet=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c=this;return(0,en.Jh)(this,function(l){return i=r.fragmentMap,a=r.context,o=r.variables,s=[n],u=function(e){return(0,en.mG)(c,void 0,void 0,function(){var u,c;return(0,en.Jh)(this,function(l){return(t||r.selectionsToResolve.has(e))&&td(e,o)?eQ(e)?[2,this.resolveField(e,t,n,r).then(function(t){var n;void 0!==t&&s.push(((n={})[eX(e)]=t,n))})]:(e1(e)?u=e:(u=i[e.name.value],__DEV__?(0,Q.kG)(u,"No fragment named ".concat(e.name.value)):(0,Q.kG)(u,11)),u&&u.typeCondition&&(c=u.typeCondition.name.value,r.fragmentMatcher(n,c,a)))?[2,this.resolveSelectionSet(u.selectionSet,t,n,r).then(function(e){s.push(e)})]:[2]:[2]})})},[2,Promise.all(e.selections.map(u)).then(function(){return tF(s)})]})})},e.prototype.resolveField=function(e,t,n,r){return(0,en.mG)(this,void 0,void 0,function(){var i,a,o,s,u,c,l,f,d,h=this;return(0,en.Jh)(this,function(p){return n?(i=r.variables,a=e.name.value,o=eX(e),s=a!==o,c=Promise.resolve(u=n[o]||n[a]),(!r.onlyRunForcedResolvers||this.shouldForceResolvers(e))&&(l=n.__typename||r.defaultOperationType,(f=this.resolvers&&this.resolvers[l])&&(d=f[s?a:o])&&(c=Promise.resolve(rX.withValue(this.cache,d,[n,eZ(e,i),r.context,{field:e,fragmentMap:r.fragmentMap},])))),[2,c.then(function(n){if(void 0===n&&(n=u),e.directives&&e.directives.forEach(function(e){"export"===e.name.value&&e.arguments&&e.arguments.forEach(function(e){"as"===e.name.value&&"StringValue"===e.value.kind&&(r.exportedVariables[e.value.value]=n)})}),!e.selectionSet||null==n)return n;var i,a,o=null!==(a=null===(i=e.directives)||void 0===i?void 0:i.some(function(e){return"client"===e.name.value}))&&void 0!==a&&a;return Array.isArray(n)?h.resolveSubSelectedArray(e,t||o,n,r):e.selectionSet?h.resolveSelectionSet(e.selectionSet,t||o,n,r):void 0})]):[2,null]})})},e.prototype.resolveSubSelectedArray=function(e,t,n,r){var i=this;return Promise.all(n.map(function(n){return null===n?null:Array.isArray(n)?i.resolveSubSelectedArray(e,t,n,r):e.selectionSet?i.resolveSelectionSet(e.selectionSet,t,n,r):void 0}))},e.prototype.collectSelectionsToResolve=function(e,t){var n=function(e){return!Array.isArray(e)},r=this.selectionsToResolveCache;function i(e){if(!r.has(e)){var a=new Set;r.set(e,a),tl(e,{Directive:function(e,t,r,i,o){"client"===e.name.value&&o.forEach(function(e){n(e)&&n8(e)&&a.add(e)})},FragmentSpread:function(e,r,o,s,u){var c=t[e.name.value];__DEV__?(0,Q.kG)(c,"No fragment named ".concat(e.name.value)):(0,Q.kG)(c,12);var l=i(c);l.size>0&&(u.forEach(function(e){n(e)&&n8(e)&&a.add(e)}),a.add(e),l.forEach(function(e){a.add(e)}))}})}return r.get(e)}return i(e)},e}(),r5=new(t_.mr?WeakMap:Map);function r6(e,t){var n=e[t];"function"==typeof n&&(e[t]=function(){return r5.set(e,(r5.get(e)+1)%1e15),n.apply(this,arguments)})}function r9(e){e.notifyTimeout&&(clearTimeout(e.notifyTimeout),e.notifyTimeout=void 0)}var r8=function(){function e(e,t){void 0===t&&(t=e.generateQueryId()),this.queryId=t,this.listeners=new Set,this.document=null,this.lastRequestId=1,this.subscriptions=new Set,this.stopped=!1,this.dirty=!1,this.observableQuery=null;var n=this.cache=e.cache;r5.has(n)||(r5.set(n,0),r6(n,"evict"),r6(n,"modify"),r6(n,"reset"))}return e.prototype.init=function(e){var t=e.networkStatus||nZ.I.loading;return this.variables&&this.networkStatus!==nZ.I.loading&&!(0,nm.D)(this.variables,e.variables)&&(t=nZ.I.setVariables),(0,nm.D)(e.variables,this.variables)||(this.lastDiff=void 0),Object.assign(this,{document:e.document,variables:e.variables,networkError:null,graphQLErrors:this.graphQLErrors||[],networkStatus:t}),e.observableQuery&&this.setObservableQuery(e.observableQuery),e.lastRequestId&&(this.lastRequestId=e.lastRequestId),this},e.prototype.reset=function(){r9(this),this.dirty=!1},e.prototype.getDiff=function(e){void 0===e&&(e=this.variables);var t=this.getDiffOptions(e);if(this.lastDiff&&(0,nm.D)(t,this.lastDiff.options))return this.lastDiff.diff;this.updateWatch(this.variables=e);var n=this.observableQuery;if(n&&"no-cache"===n.options.fetchPolicy)return{complete:!1};var r=this.cache.diff(t);return this.updateLastDiff(r,t),r},e.prototype.updateLastDiff=function(e,t){this.lastDiff=e?{diff:e,options:t||this.getDiffOptions()}:void 0},e.prototype.getDiffOptions=function(e){var t;return void 0===e&&(e=this.variables),{query:this.document,variables:e,returnPartialData:!0,optimistic:!0,canonizeResults:null===(t=this.observableQuery)||void 0===t?void 0:t.options.canonizeResults}},e.prototype.setDiff=function(e){var t=this,n=this.lastDiff&&this.lastDiff.diff;this.updateLastDiff(e),this.dirty||(0,nm.D)(n&&n.result,e&&e.result)||(this.dirty=!0,this.notifyTimeout||(this.notifyTimeout=setTimeout(function(){return t.notify()},0)))},e.prototype.setObservableQuery=function(e){var t=this;e!==this.observableQuery&&(this.oqListener&&this.listeners.delete(this.oqListener),this.observableQuery=e,e?(e.queryInfo=this,this.listeners.add(this.oqListener=function(){t.getDiff().fromOptimisticTransaction?e.observe():n4(e)})):delete this.oqListener)},e.prototype.notify=function(){var e=this;r9(this),this.shouldNotify()&&this.listeners.forEach(function(t){return t(e)}),this.dirty=!1},e.prototype.shouldNotify=function(){if(!this.dirty||!this.listeners.size)return!1;if((0,nZ.O)(this.networkStatus)&&this.observableQuery){var e=this.observableQuery.options.fetchPolicy;if("cache-only"!==e&&"cache-and-network"!==e)return!1}return!0},e.prototype.stop=function(){if(!this.stopped){this.stopped=!0,this.reset(),this.cancel(),this.cancel=e.prototype.cancel,this.subscriptions.forEach(function(e){return e.unsubscribe()});var t=this.observableQuery;t&&t.stopPolling()}},e.prototype.cancel=function(){},e.prototype.updateWatch=function(e){var t=this;void 0===e&&(e=this.variables);var n=this.observableQuery;if(!n||"no-cache"!==n.options.fetchPolicy){var r=(0,en.pi)((0,en.pi)({},this.getDiffOptions(e)),{watcher:this,callback:function(e){return t.setDiff(e)}});this.lastWatch&&(0,nm.D)(r,this.lastWatch)||(this.cancel(),this.cancel=this.cache.watch(this.lastWatch=r))}},e.prototype.resetLastWrite=function(){this.lastWrite=void 0},e.prototype.shouldWrite=function(e,t){var n=this.lastWrite;return!(n&&n.dmCount===r5.get(this.cache)&&(0,nm.D)(t,n.variables)&&(0,nm.D)(e.data,n.result.data))},e.prototype.markResult=function(e,t,n,r){var i=this,a=new tB,o=(0,tP.O)(e.errors)?e.errors.slice(0):[];if(this.reset(),"incremental"in e&&(0,tP.O)(e.incremental)){var s=tG(this.getDiff().result,e);e.data=s}else if("hasNext"in e&&e.hasNext){var u=this.getDiff();e.data=a.merge(u.result,e.data)}this.graphQLErrors=o,"no-cache"===n.fetchPolicy?this.updateLastDiff({result:e.data,complete:!0},this.getDiffOptions(n.variables)):0!==r&&(r7(e,n.errorPolicy)?this.cache.performTransaction(function(a){if(i.shouldWrite(e,n.variables))a.writeQuery({query:t,data:e.data,variables:n.variables,overwrite:1===r}),i.lastWrite={result:e,variables:n.variables,dmCount:r5.get(i.cache)};else if(i.lastDiff&&i.lastDiff.diff.complete){e.data=i.lastDiff.diff.result;return}var o=i.getDiffOptions(n.variables),s=a.diff(o);i.stopped||i.updateWatch(n.variables),i.updateLastDiff(s,o),s.complete&&(e.data=s.result)}):this.lastWrite=void 0)},e.prototype.markReady=function(){return this.networkError=null,this.networkStatus=nZ.I.ready},e.prototype.markError=function(e){return this.networkStatus=nZ.I.error,this.lastWrite=void 0,this.reset(),e.graphQLErrors&&(this.graphQLErrors=e.graphQLErrors),e.networkError&&(this.networkError=e.networkError),e},e}();function r7(e,t){void 0===t&&(t="none");var n="ignore"===t||"all"===t,r=!nO(e);return!r&&n&&e.data&&(r=!0),r}var ie=Object.prototype.hasOwnProperty,it=function(){function e(e){var t=e.cache,n=e.link,r=e.defaultOptions,i=e.queryDeduplication,a=void 0!==i&&i,o=e.onBroadcast,s=e.ssrMode,u=void 0!==s&&s,c=e.clientAwareness,l=void 0===c?{}:c,f=e.localState,d=e.assumeImmutableResults;this.clientAwareness={},this.queries=new Map,this.fetchCancelFns=new Map,this.transformCache=new(t_.mr?WeakMap:Map),this.queryIdCounter=1,this.requestIdCounter=1,this.mutationIdCounter=1,this.inFlightLinkObservables=new Map,this.cache=t,this.link=n,this.defaultOptions=r||Object.create(null),this.queryDeduplication=a,this.clientAwareness=l,this.localState=f||new r4({cache:t}),this.ssrMode=u,this.assumeImmutableResults=!!d,(this.onBroadcast=o)&&(this.mutationStore=Object.create(null))}return e.prototype.stop=function(){var e=this;this.queries.forEach(function(t,n){e.stopQueryNoBroadcast(n)}),this.cancelPendingFetches(__DEV__?new Q.ej("QueryManager stopped while query was in flight"):new Q.ej(14))},e.prototype.cancelPendingFetches=function(e){this.fetchCancelFns.forEach(function(t){return t(e)}),this.fetchCancelFns.clear()},e.prototype.mutate=function(e){var t,n,r=e.mutation,i=e.variables,a=e.optimisticResponse,o=e.updateQueries,s=e.refetchQueries,u=void 0===s?[]:s,c=e.awaitRefetchQueries,l=void 0!==c&&c,f=e.update,d=e.onQueryUpdated,h=e.fetchPolicy,p=void 0===h?(null===(t=this.defaultOptions.mutate)||void 0===t?void 0:t.fetchPolicy)||"network-only":h,b=e.errorPolicy,m=void 0===b?(null===(n=this.defaultOptions.mutate)||void 0===n?void 0:n.errorPolicy)||"none":b,g=e.keepRootFields,v=e.context;return(0,en.mG)(this,void 0,void 0,function(){var e,t,n,s,c,h;return(0,en.Jh)(this,function(b){switch(b.label){case 0:if(__DEV__?(0,Q.kG)(r,"mutation option is required. You must specify your GraphQL document in the mutation option."):(0,Q.kG)(r,15),__DEV__?(0,Q.kG)("network-only"===p||"no-cache"===p,"Mutations support only 'network-only' or 'no-cache' fetchPolicy strings. The default `network-only` behavior automatically writes mutation results to the cache. Passing `no-cache` skips the cache write."):(0,Q.kG)("network-only"===p||"no-cache"===p,16),e=this.generateMutationId(),n=(t=this.transform(r)).document,s=t.hasClientExports,r=this.cache.transformForLink(n),i=this.getVariables(r,i),!s)return[3,2];return[4,this.localState.addExportedVariables(r,i,v)];case 1:i=b.sent(),b.label=2;case 2:return c=this.mutationStore&&(this.mutationStore[e]={mutation:r,variables:i,loading:!0,error:null}),a&&this.markMutationOptimistic(a,{mutationId:e,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,updateQueries:o,update:f,keepRootFields:g}),this.broadcastQueries(),h=this,[2,new Promise(function(t,n){return nM(h.getObservableFromLink(r,(0,en.pi)((0,en.pi)({},v),{optimisticResponse:a}),i,!1),function(t){if(nO(t)&&"none"===m)throw new tN.cA({graphQLErrors:nA(t)});c&&(c.loading=!1,c.error=null);var n=(0,en.pi)({},t);return"function"==typeof u&&(u=u(n)),"ignore"===m&&nO(n)&&delete n.errors,h.markMutationResult({mutationId:e,result:n,document:r,variables:i,fetchPolicy:p,errorPolicy:m,context:v,update:f,updateQueries:o,awaitRefetchQueries:l,refetchQueries:u,removeOptimistic:a?e:void 0,onQueryUpdated:d,keepRootFields:g})}).subscribe({next:function(e){h.broadcastQueries(),"hasNext"in e&&!1!==e.hasNext||t(e)},error:function(t){c&&(c.loading=!1,c.error=t),a&&h.cache.removeOptimistic(e),h.broadcastQueries(),n(t instanceof tN.cA?t:new tN.cA({networkError:t}))}})})]}})})},e.prototype.markMutationResult=function(e,t){var n=this;void 0===t&&(t=this.cache);var r=e.result,i=[],a="no-cache"===e.fetchPolicy;if(!a&&r7(r,e.errorPolicy)){if(tU(r)||i.push({result:r.data,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}),tU(r)&&(0,tP.O)(r.incremental)){var o=t.diff({id:"ROOT_MUTATION",query:this.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0}),s=void 0;o.result&&(s=tG(o.result,r)),void 0!==s&&(r.data=s,i.push({result:s,dataId:"ROOT_MUTATION",query:e.document,variables:e.variables}))}var u=e.updateQueries;u&&this.queries.forEach(function(e,a){var o=e.observableQuery,s=o&&o.queryName;if(s&&ie.call(u,s)){var c,l=u[s],f=n.queries.get(a),d=f.document,h=f.variables,p=t.diff({query:d,variables:h,returnPartialData:!0,optimistic:!1}),b=p.result;if(p.complete&&b){var m=l(b,{mutationResult:r,queryName:d&&e3(d)||void 0,queryVariables:h});m&&i.push({result:m,dataId:"ROOT_QUERY",query:d,variables:h})}}})}if(i.length>0||e.refetchQueries||e.update||e.onQueryUpdated||e.removeOptimistic){var c=[];if(this.refetchQueries({updateCache:function(t){a||i.forEach(function(e){return t.write(e)});var o=e.update,s=!t$(r)||tU(r)&&!r.hasNext;if(o){if(!a){var u=t.diff({id:"ROOT_MUTATION",query:n.transform(e.document).asQuery,variables:e.variables,optimistic:!1,returnPartialData:!0});u.complete&&("incremental"in(r=(0,en.pi)((0,en.pi)({},r),{data:u.result}))&&delete r.incremental,"hasNext"in r&&delete r.hasNext)}s&&o(t,r,{context:e.context,variables:e.variables})}a||e.keepRootFields||!s||t.modify({id:"ROOT_MUTATION",fields:function(e,t){var n=t.fieldName,r=t.DELETE;return"__typename"===n?e:r}})},include:e.refetchQueries,optimistic:!1,removeOptimistic:e.removeOptimistic,onQueryUpdated:e.onQueryUpdated||null}).forEach(function(e){return c.push(e)}),e.awaitRefetchQueries||e.onQueryUpdated)return Promise.all(c).then(function(){return r})}return Promise.resolve(r)},e.prototype.markMutationOptimistic=function(e,t){var n=this,r="function"==typeof e?e(t.variables):e;return this.cache.recordOptimisticTransaction(function(e){try{n.markMutationResult((0,en.pi)((0,en.pi)({},t),{result:{data:r}}),e)}catch(i){__DEV__&&Q.kG.error(i)}},t.mutationId)},e.prototype.fetchQuery=function(e,t,n){return this.fetchQueryObservable(e,t,n).promise},e.prototype.getQueryStore=function(){var e=Object.create(null);return this.queries.forEach(function(t,n){e[n]={variables:t.variables,networkStatus:t.networkStatus,networkError:t.networkError,graphQLErrors:t.graphQLErrors}}),e},e.prototype.resetErrors=function(e){var t=this.queries.get(e);t&&(t.networkError=void 0,t.graphQLErrors=[])},e.prototype.transform=function(e){var t=this.transformCache;if(!t.has(e)){var n=this.cache.transformDocument(e),r=nY(n),i=this.localState.clientQuery(n),a=r&&this.localState.serverQuery(r),o={document:n,hasClientExports:tm(n),hasForcedResolvers:this.localState.shouldForceResolvers(n),clientQuery:i,serverQuery:a,defaultVars:e8(e2(n)),asQuery:(0,en.pi)((0,en.pi)({},n),{definitions:n.definitions.map(function(e){return"OperationDefinition"===e.kind&&"query"!==e.operation?(0,en.pi)((0,en.pi)({},e),{operation:"query"}):e})})},s=function(e){e&&!t.has(e)&&t.set(e,o)};s(e),s(n),s(i),s(a)}return t.get(e)},e.prototype.getVariables=function(e,t){return(0,en.pi)((0,en.pi)({},this.transform(e).defaultVars),t)},e.prototype.watchQuery=function(e){void 0===(e=(0,en.pi)((0,en.pi)({},e),{variables:this.getVariables(e.query,e.variables)})).notifyOnNetworkStatusChange&&(e.notifyOnNetworkStatusChange=!1);var t=new r8(this),n=new n3({queryManager:this,queryInfo:t,options:e});return this.queries.set(n.queryId,t),t.init({document:n.query,observableQuery:n,variables:n.variables}),n},e.prototype.query=function(e,t){var n=this;return void 0===t&&(t=this.generateQueryId()),__DEV__?(0,Q.kG)(e.query,"query option is required. You must specify your GraphQL document in the query option."):(0,Q.kG)(e.query,17),__DEV__?(0,Q.kG)("Document"===e.query.kind,'You must wrap the query string in a "gql" tag.'):(0,Q.kG)("Document"===e.query.kind,18),__DEV__?(0,Q.kG)(!e.returnPartialData,"returnPartialData option only supported on watchQuery."):(0,Q.kG)(!e.returnPartialData,19),__DEV__?(0,Q.kG)(!e.pollInterval,"pollInterval option only supported on watchQuery."):(0,Q.kG)(!e.pollInterval,20),this.fetchQuery(t,e).finally(function(){return n.stopQuery(t)})},e.prototype.generateQueryId=function(){return String(this.queryIdCounter++)},e.prototype.generateRequestId=function(){return this.requestIdCounter++},e.prototype.generateMutationId=function(){return String(this.mutationIdCounter++)},e.prototype.stopQueryInStore=function(e){this.stopQueryInStoreNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryInStoreNoBroadcast=function(e){var t=this.queries.get(e);t&&t.stop()},e.prototype.clearStore=function(e){return void 0===e&&(e={discardWatches:!0}),this.cancelPendingFetches(__DEV__?new Q.ej("Store reset while query was in flight (not completed in link chain)"):new Q.ej(21)),this.queries.forEach(function(e){e.observableQuery?e.networkStatus=nZ.I.loading:e.stop()}),this.mutationStore&&(this.mutationStore=Object.create(null)),this.cache.reset(e)},e.prototype.getObservableQueries=function(e){var t=this;void 0===e&&(e="active");var n=new Map,r=new Map,i=new Set;return Array.isArray(e)&&e.forEach(function(e){"string"==typeof e?r.set(e,!1):eN(e)?r.set(t.transform(e).document,!1):(0,eO.s)(e)&&e.query&&i.add(e)}),this.queries.forEach(function(t,i){var a=t.observableQuery,o=t.document;if(a){if("all"===e){n.set(i,a);return}var s=a.queryName;if("standby"===a.options.fetchPolicy||"active"===e&&!a.hasObservers())return;("active"===e||s&&r.has(s)||o&&r.has(o))&&(n.set(i,a),s&&r.set(s,!0),o&&r.set(o,!0))}}),i.size&&i.forEach(function(e){var r=nG("legacyOneTimeQuery"),i=t.getQuery(r).init({document:e.query,variables:e.variables}),a=new n3({queryManager:t,queryInfo:i,options:(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"network-only"})});(0,Q.kG)(a.queryId===r),i.setObservableQuery(a),n.set(r,a)}),__DEV__&&r.size&&r.forEach(function(e,t){!e&&__DEV__&&Q.kG.warn("Unknown query ".concat("string"==typeof t?"named ":"").concat(JSON.stringify(t,null,2)," requested in refetchQueries options.include array"))}),n},e.prototype.reFetchObservableQueries=function(e){var t=this;void 0===e&&(e=!1);var n=[];return this.getObservableQueries(e?"all":"active").forEach(function(r,i){var a=r.options.fetchPolicy;r.resetLastResults(),(e||"standby"!==a&&"cache-only"!==a)&&n.push(r.refetch()),t.getQuery(i).setDiff(null)}),this.broadcastQueries(),Promise.all(n)},e.prototype.setObservableQuery=function(e){this.getQuery(e.queryId).setObservableQuery(e)},e.prototype.startGraphQLSubscription=function(e){var t=this,n=e.query,r=e.fetchPolicy,i=e.errorPolicy,a=e.variables,o=e.context,s=void 0===o?{}:o;n=this.transform(n).document,a=this.getVariables(n,a);var u=function(e){return t.getObservableFromLink(n,s,e).map(function(a){"no-cache"!==r&&(r7(a,i)&&t.cache.write({query:n,result:a.data,dataId:"ROOT_SUBSCRIPTION",variables:e}),t.broadcastQueries());var o=nO(a),s=(0,tN.ls)(a);if(o||s){var u={};throw o&&(u.graphQLErrors=a.errors),s&&(u.protocolErrors=a.extensions[tN.YG]),new tN.cA(u)}return a})};if(this.transform(n).hasClientExports){var c=this.localState.addExportedVariables(n,a,s).then(u);return new eT(function(e){var t=null;return c.then(function(n){return t=n.subscribe(e)},e.error),function(){return t&&t.unsubscribe()}})}return u(a)},e.prototype.stopQuery=function(e){this.stopQueryNoBroadcast(e),this.broadcastQueries()},e.prototype.stopQueryNoBroadcast=function(e){this.stopQueryInStoreNoBroadcast(e),this.removeQuery(e)},e.prototype.removeQuery=function(e){this.fetchCancelFns.delete(e),this.queries.has(e)&&(this.getQuery(e).stop(),this.queries.delete(e))},e.prototype.broadcastQueries=function(){this.onBroadcast&&this.onBroadcast(),this.queries.forEach(function(e){return e.notify()})},e.prototype.getLocalState=function(){return this.localState},e.prototype.getObservableFromLink=function(e,t,n,r){var i,a,o=this;void 0===r&&(r=null!==(i=null==t?void 0:t.queryDeduplication)&&void 0!==i?i:this.queryDeduplication);var s=this.transform(e).serverQuery;if(s){var u=this,c=u.inFlightLinkObservables,l=u.link,f={query:s,variables:n,operationName:e3(s)||void 0,context:this.prepareContext((0,en.pi)((0,en.pi)({},t),{forceFetch:!r}))};if(t=f.context,r){var d=c.get(s)||new Map;c.set(s,d);var h=nx(n);if(!(a=d.get(h))){var p=new nq([np(l,f)]);d.set(h,a=p),p.beforeNext(function(){d.delete(h)&&d.size<1&&c.delete(s)})}}else a=new nq([np(l,f)])}else a=new nq([eT.of({data:{}})]),t=this.prepareContext(t);var b=this.transform(e).clientQuery;return b&&(a=nM(a,function(e){return o.localState.runResolvers({document:b,remoteResult:e,context:t,variables:n})})),a},e.prototype.getResultsFromLink=function(e,t,n){var r=e.lastRequestId=this.generateRequestId(),i=this.cache.transformForLink(this.transform(e.document).document);return nM(this.getObservableFromLink(i,n.context,n.variables),function(a){var o=nA(a),s=o.length>0;if(r>=e.lastRequestId){if(s&&"none"===n.errorPolicy)throw e.markError(new tN.cA({graphQLErrors:o}));e.markResult(a,i,n,t),e.markReady()}var u={data:a.data,loading:!1,networkStatus:nZ.I.ready};return s&&"ignore"!==n.errorPolicy&&(u.errors=o,u.networkStatus=nZ.I.error),u},function(t){var n=(0,tN.MS)(t)?t:new tN.cA({networkError:t});throw r>=e.lastRequestId&&e.markError(n),n})},e.prototype.fetchQueryObservable=function(e,t,n){return this.fetchConcastWithInfo(e,t,n).concast},e.prototype.fetchConcastWithInfo=function(e,t,n){var r,i,a=this;void 0===n&&(n=nZ.I.loading);var o=this.transform(t.query).document,s=this.getVariables(o,t.variables),u=this.getQuery(e),c=this.defaultOptions.watchQuery,l=t.fetchPolicy,f=void 0===l?c&&c.fetchPolicy||"cache-first":l,d=t.errorPolicy,h=void 0===d?c&&c.errorPolicy||"none":d,p=t.returnPartialData,b=void 0!==p&&p,m=t.notifyOnNetworkStatusChange,g=void 0!==m&&m,v=t.context,y=void 0===v?{}:v,w=Object.assign({},t,{query:o,variables:s,fetchPolicy:f,errorPolicy:h,returnPartialData:b,notifyOnNetworkStatusChange:g,context:y}),_=function(e){w.variables=e;var r=a.fetchQueryByPolicy(u,w,n);return"standby"!==w.fetchPolicy&&r.sources.length>0&&u.observableQuery&&u.observableQuery.applyNextFetchPolicy("after-fetch",t),r},E=function(){return a.fetchCancelFns.delete(e)};if(this.fetchCancelFns.set(e,function(e){E(),setTimeout(function(){return r.cancel(e)})}),this.transform(w.query).hasClientExports)r=new nq(this.localState.addExportedVariables(w.query,w.variables,w.context).then(_).then(function(e){return e.sources})),i=!0;else{var S=_(w.variables);i=S.fromLink,r=new nq(S.sources)}return r.promise.then(E,E),{concast:r,fromLink:i}},e.prototype.refetchQueries=function(e){var t=this,n=e.updateCache,r=e.include,i=e.optimistic,a=void 0!==i&&i,o=e.removeOptimistic,s=void 0===o?a?nG("refetchQueries"):void 0:o,u=e.onQueryUpdated,c=new Map;r&&this.getObservableQueries(r).forEach(function(e,n){c.set(n,{oq:e,lastDiff:t.getQuery(n).getDiff()})});var l=new Map;return n&&this.cache.batch({update:n,optimistic:a&&s||!1,removeOptimistic:s,onWatchUpdated:function(e,t,n){var r=e.watcher instanceof r8&&e.watcher.observableQuery;if(r){if(u){c.delete(r.queryId);var i=u(r,t,n);return!0===i&&(i=r.refetch()),!1!==i&&l.set(r,i),i}null!==u&&c.set(r.queryId,{oq:r,lastDiff:n,diff:t})}}}),c.size&&c.forEach(function(e,n){var r,i=e.oq,a=e.lastDiff,o=e.diff;if(u){if(!o){var s=i.queryInfo;s.reset(),o=s.getDiff()}r=u(i,o,a)}u&&!0!==r||(r=i.refetch()),!1!==r&&l.set(i,r),n.indexOf("legacyOneTimeQuery")>=0&&t.stopQueryNoBroadcast(n)}),s&&this.cache.removeOptimistic(s),l},e.prototype.fetchQueryByPolicy=function(e,t,n){var r=this,i=t.query,a=t.variables,o=t.fetchPolicy,s=t.refetchWritePolicy,u=t.errorPolicy,c=t.returnPartialData,l=t.context,f=t.notifyOnNetworkStatusChange,d=e.networkStatus;e.init({document:this.transform(i).document,variables:a,networkStatus:n});var h=function(){return e.getDiff(a)},p=function(t,n){void 0===n&&(n=e.networkStatus||nZ.I.loading);var o=t.result;!__DEV__||c||(0,nm.D)(o,{})||n6(t.missing);var s=function(e){return eT.of((0,en.pi)({data:e,loading:(0,nZ.O)(n),networkStatus:n},t.complete?null:{partial:!0}))};return o&&r.transform(i).hasForcedResolvers?r.localState.runResolvers({document:i,remoteResult:{data:o},context:l,variables:a,onlyRunForcedResolvers:!0}).then(function(e){return s(e.data||void 0)}):"none"===u&&n===nZ.I.refetch&&Array.isArray(t.missing)?s(void 0):s(o)},b="no-cache"===o?0:n===nZ.I.refetch&&"merge"!==s?1:2,m=function(){return r.getResultsFromLink(e,b,{variables:a,context:l,fetchPolicy:o,errorPolicy:u})},g=f&&"number"==typeof d&&d!==n&&(0,nZ.O)(n);switch(o){default:case"cache-first":var v=h();if(v.complete)return{fromLink:!1,sources:[p(v,e.markReady())]};if(c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-and-network":var v=h();if(v.complete||c||g)return{fromLink:!0,sources:[p(v),m()]};return{fromLink:!0,sources:[m()]};case"cache-only":return{fromLink:!1,sources:[p(h(),e.markReady())]};case"network-only":if(g)return{fromLink:!0,sources:[p(h()),m()]};return{fromLink:!0,sources:[m()]};case"no-cache":if(g)return{fromLink:!0,sources:[p(e.getDiff()),m(),]};return{fromLink:!0,sources:[m()]};case"standby":return{fromLink:!1,sources:[]}}},e.prototype.getQuery=function(e){return e&&!this.queries.has(e)&&this.queries.set(e,new r8(this,e)),this.queries.get(e)},e.prototype.prepareContext=function(e){void 0===e&&(e={});var t=this.localState.prepareContext(e);return(0,en.pi)((0,en.pi)({},t),{clientAwareness:this.clientAwareness})},e}(),ir=__webpack_require__(14012),ii=!1,ia=function(){function e(e){var t=this;this.resetStoreCallbacks=[],this.clearStoreCallbacks=[];var n=e.uri,r=e.credentials,i=e.headers,a=e.cache,o=e.ssrMode,s=void 0!==o&&o,u=e.ssrForceFetchDelay,c=void 0===u?0:u,l=e.connectToDevTools,f=void 0===l?"object"==typeof window&&!window.__APOLLO_CLIENT__&&__DEV__:l,d=e.queryDeduplication,h=void 0===d||d,p=e.defaultOptions,b=e.assumeImmutableResults,m=void 0!==b&&b,g=e.resolvers,v=e.typeDefs,y=e.fragmentMatcher,w=e.name,_=e.version,E=e.link;if(E||(E=n?new nh({uri:n,credentials:r,headers:i}):ta.empty()),!a)throw __DEV__?new Q.ej("To initialize Apollo Client, you must specify a 'cache' property in the options object. \nFor more information, please visit: https://go.apollo.dev/c/docs"):new Q.ej(9);if(this.link=E,this.cache=a,this.disableNetworkFetches=s||c>0,this.queryDeduplication=h,this.defaultOptions=p||Object.create(null),this.typeDefs=v,c&&setTimeout(function(){return t.disableNetworkFetches=!1},c),this.watchQuery=this.watchQuery.bind(this),this.query=this.query.bind(this),this.mutate=this.mutate.bind(this),this.resetStore=this.resetStore.bind(this),this.reFetchObservableQueries=this.reFetchObservableQueries.bind(this),f&&"object"==typeof window&&(window.__APOLLO_CLIENT__=this),!ii&&f&&__DEV__&&(ii=!0,"undefined"!=typeof window&&window.document&&window.top===window.self&&!window.__APOLLO_DEVTOOLS_GLOBAL_HOOK__)){var S=window.navigator,k=S&&S.userAgent,x=void 0;"string"==typeof k&&(k.indexOf("Chrome/")>-1?x="https://chrome.google.com/webstore/detail/apollo-client-developer-t/jdkknkkbebbapilgoeccciglkfbmbnfm":k.indexOf("Firefox/")>-1&&(x="https://addons.mozilla.org/en-US/firefox/addon/apollo-developer-tools/")),x&&__DEV__&&Q.kG.log("Download the Apollo DevTools for a better development experience: "+x)}this.version=nb,this.localState=new r4({cache:a,client:this,resolvers:g,fragmentMatcher:y}),this.queryManager=new it({cache:this.cache,link:this.link,defaultOptions:this.defaultOptions,queryDeduplication:h,ssrMode:s,clientAwareness:{name:w,version:_},localState:this.localState,assumeImmutableResults:m,onBroadcast:f?function(){t.devToolsHookCb&&t.devToolsHookCb({action:{},state:{queries:t.queryManager.getQueryStore(),mutations:t.queryManager.mutationStore||{}},dataWithOptimisticResults:t.cache.extract(!0)})}:void 0})}return e.prototype.stop=function(){this.queryManager.stop()},e.prototype.watchQuery=function(e){return this.defaultOptions.watchQuery&&(e=(0,ir.J)(this.defaultOptions.watchQuery,e)),this.disableNetworkFetches&&("network-only"===e.fetchPolicy||"cache-and-network"===e.fetchPolicy)&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.watchQuery(e)},e.prototype.query=function(e){return this.defaultOptions.query&&(e=(0,ir.J)(this.defaultOptions.query,e)),__DEV__?(0,Q.kG)("cache-and-network"!==e.fetchPolicy,"The cache-and-network fetchPolicy does not work with client.query, because client.query can only return a single result. Please use client.watchQuery to receive multiple results from the cache and the network, or consider using a different fetchPolicy, such as cache-first or network-only."):(0,Q.kG)("cache-and-network"!==e.fetchPolicy,10),this.disableNetworkFetches&&"network-only"===e.fetchPolicy&&(e=(0,en.pi)((0,en.pi)({},e),{fetchPolicy:"cache-first"})),this.queryManager.query(e)},e.prototype.mutate=function(e){return this.defaultOptions.mutate&&(e=(0,ir.J)(this.defaultOptions.mutate,e)),this.queryManager.mutate(e)},e.prototype.subscribe=function(e){return this.queryManager.startGraphQLSubscription(e)},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!1),this.cache.readQuery(e,t)},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!1),this.cache.readFragment(e,t)},e.prototype.writeQuery=function(e){var t=this.cache.writeQuery(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.writeFragment=function(e){var t=this.cache.writeFragment(e);return!1!==e.broadcast&&this.queryManager.broadcastQueries(),t},e.prototype.__actionHookForDevTools=function(e){this.devToolsHookCb=e},e.prototype.__requestRaw=function(e){return np(this.link,e)},e.prototype.resetStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!1})}).then(function(){return Promise.all(e.resetStoreCallbacks.map(function(e){return e()}))}).then(function(){return e.reFetchObservableQueries()})},e.prototype.clearStore=function(){var e=this;return Promise.resolve().then(function(){return e.queryManager.clearStore({discardWatches:!0})}).then(function(){return Promise.all(e.clearStoreCallbacks.map(function(e){return e()}))})},e.prototype.onResetStore=function(e){var t=this;return this.resetStoreCallbacks.push(e),function(){t.resetStoreCallbacks=t.resetStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.onClearStore=function(e){var t=this;return this.clearStoreCallbacks.push(e),function(){t.clearStoreCallbacks=t.clearStoreCallbacks.filter(function(t){return t!==e})}},e.prototype.reFetchObservableQueries=function(e){return this.queryManager.reFetchObservableQueries(e)},e.prototype.refetchQueries=function(e){var t=this.queryManager.refetchQueries(e),n=[],r=[];t.forEach(function(e,t){n.push(t),r.push(e)});var i=Promise.all(r);return i.queries=n,i.results=r,i.catch(function(e){__DEV__&&Q.kG.debug("In client.refetchQueries, Promise.all promise rejected with error ".concat(e))}),i},e.prototype.getObservableQueries=function(e){return void 0===e&&(e="active"),this.queryManager.getObservableQueries(e)},e.prototype.extract=function(e){return this.cache.extract(e)},e.prototype.restore=function(e){return this.cache.restore(e)},e.prototype.addResolvers=function(e){this.localState.addResolvers(e)},e.prototype.setResolvers=function(e){this.localState.setResolvers(e)},e.prototype.getResolvers=function(){return this.localState.getResolvers()},e.prototype.setLocalStateFragmentMatcher=function(e){this.localState.setFragmentMatcher(e)},e.prototype.setLink=function(e){this.link=this.queryManager.link=e},e}(),io=function(){function e(){this.getFragmentDoc=rZ(eA)}return e.prototype.batch=function(e){var t,n=this,r="string"==typeof e.optimistic?e.optimistic:!1===e.optimistic?null:void 0;return this.performTransaction(function(){return t=e.update(n)},r),t},e.prototype.recordOptimisticTransaction=function(e,t){this.performTransaction(e,t)},e.prototype.transformDocument=function(e){return e},e.prototype.transformForLink=function(e){return e},e.prototype.identify=function(e){},e.prototype.gc=function(){return[]},e.prototype.modify=function(e){return!1},e.prototype.readQuery=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{rootId:e.id||"ROOT_QUERY",optimistic:t}))},e.prototype.readFragment=function(e,t){return void 0===t&&(t=!!e.optimistic),this.read((0,en.pi)((0,en.pi)({},e),{query:this.getFragmentDoc(e.fragment,e.fragmentName),rootId:e.id,optimistic:t}))},e.prototype.writeQuery=function(e){var t=e.id,n=e.data,r=(0,en._T)(e,["id","data"]);return this.write(Object.assign(r,{dataId:t||"ROOT_QUERY",result:n}))},e.prototype.writeFragment=function(e){var t=e.id,n=e.data,r=e.fragment,i=e.fragmentName,a=(0,en._T)(e,["id","data","fragment","fragmentName"]);return this.write(Object.assign(a,{query:this.getFragmentDoc(r,i),dataId:t,result:n}))},e.prototype.updateQuery=function(e,t){return this.batch({update:function(n){var r=n.readQuery(e),i=t(r);return null==i?r:(n.writeQuery((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e.prototype.updateFragment=function(e,t){return this.batch({update:function(n){var r=n.readFragment(e),i=t(r);return null==i?r:(n.writeFragment((0,en.pi)((0,en.pi)({},e),{data:i})),i)}})},e}(),is=function(e){function t(n,r,i,a){var o,s=e.call(this,n)||this;if(s.message=n,s.path=r,s.query=i,s.variables=a,Array.isArray(s.path)){s.missing=s.message;for(var u=s.path.length-1;u>=0;--u)s.missing=((o={})[s.path[u]]=s.missing,o)}else s.missing=s.path;return s.__proto__=t.prototype,s}return(0,en.ZT)(t,e),t}(Error),iu=__webpack_require__(10542),ic=Object.prototype.hasOwnProperty;function il(e){return null==e}function id(e,t){var n=e.__typename,r=e.id,i=e._id;if("string"==typeof n&&(t&&(t.keyObject=il(r)?il(i)?void 0:{_id:i}:{id:r}),il(r)&&!il(i)&&(r=i),!il(r)))return"".concat(n,":").concat("number"==typeof r||"string"==typeof r?r:JSON.stringify(r))}var ih={dataIdFromObject:id,addTypename:!0,resultCaching:!0,canonizeResults:!1};function ip(e){return(0,n1.o)(ih,e)}function ib(e){var t=e.canonizeResults;return void 0===t?ih.canonizeResults:t}function im(e,t){return eD(t)?e.get(t.__ref,"__typename"):t&&t.__typename}var ig=/^[_a-z][_0-9a-z]*/i;function iv(e){var t=e.match(ig);return t?t[0]:e}function iy(e,t,n){return!!(0,eO.s)(t)&&((0,tP.k)(t)?t.every(function(t){return iy(e,t,n)}):e.selections.every(function(e){if(eQ(e)&&td(e,n)){var r=eX(e);return ic.call(t,r)&&(!e.selectionSet||iy(e.selectionSet,t[r],n))}return!0}))}function iw(e){return(0,eO.s)(e)&&!eD(e)&&!(0,tP.k)(e)}function i_(){return new tB}function iE(e,t){var n=eL(e4(e));return{fragmentMap:n,lookupFragment:function(e){var r=n[e];return!r&&t&&(r=t.lookup(e)),r||null}}}var iS=Object.create(null),ik=function(){return iS},ix=Object.create(null),iT=function(){function e(e,t){var n=this;this.policies=e,this.group=t,this.data=Object.create(null),this.rootIds=Object.create(null),this.refs=Object.create(null),this.getFieldValue=function(e,t){return(0,iu.J)(eD(e)?n.get(e.__ref,t):e&&e[t])},this.canRead=function(e){return eD(e)?n.has(e.__ref):"object"==typeof e},this.toReference=function(e,t){if("string"==typeof e)return eI(e);if(eD(e))return e;var r=n.policies.identify(e)[0];if(r){var i=eI(r);return t&&n.merge(r,e),i}}}return e.prototype.toObject=function(){return(0,en.pi)({},this.data)},e.prototype.has=function(e){return void 0!==this.lookup(e,!0)},e.prototype.get=function(e,t){if(this.group.depend(e,t),ic.call(this.data,e)){var n=this.data[e];if(n&&ic.call(n,t))return n[t]}return"__typename"===t&&ic.call(this.policies.rootTypenamesById,e)?this.policies.rootTypenamesById[e]:this instanceof iL?this.parent.get(e,t):void 0},e.prototype.lookup=function(e,t){return(t&&this.group.depend(e,"__exists"),ic.call(this.data,e))?this.data[e]:this instanceof iL?this.parent.lookup(e,t):this.policies.rootTypenamesById[e]?Object.create(null):void 0},e.prototype.merge=function(e,t){var n,r=this;eD(e)&&(e=e.__ref),eD(t)&&(t=t.__ref);var i="string"==typeof e?this.lookup(n=e):e,a="string"==typeof t?this.lookup(n=t):t;if(a){__DEV__?(0,Q.kG)("string"==typeof n,"store.merge expects a string ID"):(0,Q.kG)("string"==typeof n,1);var o=new tB(iI).merge(i,a);if(this.data[n]=o,o!==i&&(delete this.refs[n],this.group.caching)){var s=Object.create(null);i||(s.__exists=1),Object.keys(a).forEach(function(e){if(!i||i[e]!==o[e]){s[e]=1;var t=iv(e);t===e||r.policies.hasKeyArgs(o.__typename,t)||(s[t]=1),void 0!==o[e]||r instanceof iL||delete o[e]}}),s.__typename&&!(i&&i.__typename)&&this.policies.rootTypenamesById[n]===o.__typename&&delete s.__typename,Object.keys(s).forEach(function(e){return r.group.dirty(n,e)})}}},e.prototype.modify=function(e,t){var n=this,r=this.lookup(e);if(r){var i=Object.create(null),a=!1,o=!0,s={DELETE:iS,INVALIDATE:ix,isReference:eD,toReference:this.toReference,canRead:this.canRead,readField:function(t,r){return n.policies.readField("string"==typeof t?{fieldName:t,from:r||eI(e)}:t,{store:n})}};if(Object.keys(r).forEach(function(u){var c=iv(u),l=r[u];if(void 0!==l){var f="function"==typeof t?t:t[u]||t[c];if(f){var d=f===ik?iS:f((0,iu.J)(l),(0,en.pi)((0,en.pi)({},s),{fieldName:c,storeFieldName:u,storage:n.getStorage(e,u)}));d===ix?n.group.dirty(e,u):(d===iS&&(d=void 0),d!==l&&(i[u]=d,a=!0,l=d))}void 0!==l&&(o=!1)}}),a)return this.merge(e,i),o&&(this instanceof iL?this.data[e]=void 0:delete this.data[e],this.group.dirty(e,"__exists")),!0}return!1},e.prototype.delete=function(e,t,n){var r,i=this.lookup(e);if(i){var a=this.getFieldValue(i,"__typename"),o=t&&n?this.policies.getStoreFieldName({typename:a,fieldName:t,args:n}):t;return this.modify(e,o?((r={})[o]=ik,r):ik)}return!1},e.prototype.evict=function(e,t){var n=!1;return e.id&&(ic.call(this.data,e.id)&&(n=this.delete(e.id,e.fieldName,e.args)),this instanceof iL&&this!==t&&(n=this.parent.evict(e,t)||n),(e.fieldName||n)&&this.group.dirty(e.id,e.fieldName||"__exists")),n},e.prototype.clear=function(){this.replace(null)},e.prototype.extract=function(){var e=this,t=this.toObject(),n=[];return this.getRootIdSet().forEach(function(t){ic.call(e.policies.rootTypenamesById,t)||n.push(t)}),n.length&&(t.__META={extraRootIds:n.sort()}),t},e.prototype.replace=function(e){var t=this;if(Object.keys(this.data).forEach(function(n){e&&ic.call(e,n)||t.delete(n)}),e){var n=e.__META,r=(0,en._T)(e,["__META"]);Object.keys(r).forEach(function(e){t.merge(e,r[e])}),n&&n.extraRootIds.forEach(this.retain,this)}},e.prototype.retain=function(e){return this.rootIds[e]=(this.rootIds[e]||0)+1},e.prototype.release=function(e){if(this.rootIds[e]>0){var t=--this.rootIds[e];return t||delete this.rootIds[e],t}return 0},e.prototype.getRootIdSet=function(e){return void 0===e&&(e=new Set),Object.keys(this.rootIds).forEach(e.add,e),this instanceof iL?this.parent.getRootIdSet(e):Object.keys(this.policies.rootTypenamesById).forEach(e.add,e),e},e.prototype.gc=function(){var e=this,t=this.getRootIdSet(),n=this.toObject();t.forEach(function(r){ic.call(n,r)&&(Object.keys(e.findChildRefIds(r)).forEach(t.add,t),delete n[r])});var r=Object.keys(n);if(r.length){for(var i=this;i instanceof iL;)i=i.parent;r.forEach(function(e){return i.delete(e)})}return r},e.prototype.findChildRefIds=function(e){if(!ic.call(this.refs,e)){var t=this.refs[e]=Object.create(null),n=this.data[e];if(!n)return t;var r=new Set([n]);r.forEach(function(e){eD(e)&&(t[e.__ref]=!0),(0,eO.s)(e)&&Object.keys(e).forEach(function(t){var n=e[t];(0,eO.s)(n)&&r.add(n)})})}return this.refs[e]},e.prototype.makeCacheKey=function(){return this.group.keyMaker.lookupArray(arguments)},e}(),iM=function(){function e(e,t){void 0===t&&(t=null),this.caching=e,this.parent=t,this.d=null,this.resetCaching()}return e.prototype.resetCaching=function(){this.d=this.caching?rW():null,this.keyMaker=new n_(t_.mr)},e.prototype.depend=function(e,t){if(this.d){this.d(iO(e,t));var n=iv(t);n!==t&&this.d(iO(e,n)),this.parent&&this.parent.depend(e,t)}},e.prototype.dirty=function(e,t){this.d&&this.d.dirty(iO(e,t),"__exists"===t?"forget":"setDirty")},e}();function iO(e,t){return t+"#"+e}function iA(e,t){iD(e)&&e.group.depend(t,"__exists")}!function(e){var t=function(e){function t(t){var n=t.policies,r=t.resultCaching,i=void 0===r||r,a=t.seed,o=e.call(this,n,new iM(i))||this;return o.stump=new iC(o),o.storageTrie=new n_(t_.mr),a&&o.replace(a),o}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,t){return this.stump.addLayer(e,t)},t.prototype.removeLayer=function(){return this},t.prototype.getStorage=function(){return this.storageTrie.lookupArray(arguments)},t}(e);e.Root=t}(iT||(iT={}));var iL=function(e){function t(t,n,r,i){var a=e.call(this,n.policies,i)||this;return a.id=t,a.parent=n,a.replay=r,a.group=i,r(a),a}return(0,en.ZT)(t,e),t.prototype.addLayer=function(e,n){return new t(e,this,n,this.group)},t.prototype.removeLayer=function(e){var t=this,n=this.parent.removeLayer(e);return e===this.id?(this.group.caching&&Object.keys(this.data).forEach(function(e){var r=t.data[e],i=n.lookup(e);i?r?r!==i&&Object.keys(r).forEach(function(n){(0,nm.D)(r[n],i[n])||t.group.dirty(e,n)}):(t.group.dirty(e,"__exists"),Object.keys(i).forEach(function(n){t.group.dirty(e,n)})):t.delete(e)}),n):n===this.parent?this:n.addLayer(this.id,this.replay)},t.prototype.toObject=function(){return(0,en.pi)((0,en.pi)({},this.parent.toObject()),this.data)},t.prototype.findChildRefIds=function(t){var n=this.parent.findChildRefIds(t);return ic.call(this.data,t)?(0,en.pi)((0,en.pi)({},n),e.prototype.findChildRefIds.call(this,t)):n},t.prototype.getStorage=function(){for(var e=this.parent;e.parent;)e=e.parent;return e.getStorage.apply(e,arguments)},t}(iT),iC=function(e){function t(t){return e.call(this,"EntityStore.Stump",t,function(){},new iM(t.group.caching,t.group))||this}return(0,en.ZT)(t,e),t.prototype.removeLayer=function(){return this},t.prototype.merge=function(){return this.parent.merge.apply(this.parent,arguments)},t}(iL);function iI(e,t,n){var r=e[n],i=t[n];return(0,nm.D)(r,i)?r:i}function iD(e){return!!(e instanceof iT&&e.group.caching)}function iN(e){return[e.selectionSet,e.objectOrReference,e.context,e.context.canonizeResults,]}var iP=function(){function e(e){var t=this;this.knownResults=new(t_.mr?WeakMap:Map),this.config=(0,n1.o)(e,{addTypename:!1!==e.addTypename,canonizeResults:ib(e)}),this.canon=e.canon||new nk,this.executeSelectionSet=rZ(function(e){var n,r=e.context.canonizeResults,i=iN(e);i[3]=!r;var a=(n=t.executeSelectionSet).peek.apply(n,i);return a?r?(0,en.pi)((0,en.pi)({},a),{result:t.canon.admit(a.result)}):a:(iA(e.context.store,e.enclosingRef.__ref),t.execSelectionSetImpl(e))},{max:this.config.resultCacheMaxSize,keyArgs:iN,makeCacheKey:function(e,t,n,r){if(iD(n.store))return n.store.makeCacheKey(e,eD(t)?t.__ref:t,n.varString,r)}}),this.executeSubSelectedArray=rZ(function(e){return iA(e.context.store,e.enclosingRef.__ref),t.execSubSelectedArrayImpl(e)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var t=e.field,n=e.array,r=e.context;if(iD(r.store))return r.store.makeCacheKey(t,n,r.varString)}})}return e.prototype.resetCanon=function(){this.canon=new nk},e.prototype.diffQueryAgainstStore=function(e){var t,n=e.store,r=e.query,i=e.rootId,a=void 0===i?"ROOT_QUERY":i,o=e.variables,s=e.returnPartialData,u=void 0===s||s,c=e.canonizeResults,l=void 0===c?this.config.canonizeResults:c,f=this.config.cache.policies;o=(0,en.pi)((0,en.pi)({},e8(e5(r))),o);var d=eI(a),h=this.executeSelectionSet({selectionSet:e9(r).selectionSet,objectOrReference:d,enclosingRef:d,context:(0,en.pi)({store:n,query:r,policies:f,variables:o,varString:nx(o),canonizeResults:l},iE(r,this.config.fragments))});if(h.missing&&(t=[new is(iR(h.missing),h.missing,r,o)],!u))throw t[0];return{result:h.result,complete:!t,missing:t}},e.prototype.isFresh=function(e,t,n,r){if(iD(r.store)&&this.knownResults.get(e)===n){var i=this.executeSelectionSet.peek(n,t,r,this.canon.isKnown(e));if(i&&e===i.result)return!0}return!1},e.prototype.execSelectionSetImpl=function(e){var t,n=this,r=e.selectionSet,i=e.objectOrReference,a=e.enclosingRef,o=e.context;if(eD(i)&&!o.policies.rootTypenamesById[i.__ref]&&!o.store.has(i.__ref))return{result:this.canon.empty,missing:"Dangling reference to missing ".concat(i.__ref," object")};var s=o.variables,u=o.policies,c=o.store.getFieldValue(i,"__typename"),l=[],f=new tB;function d(e,n){var r;return e.missing&&(t=f.merge(t,((r={})[n]=e.missing,r))),e.result}this.config.addTypename&&"string"==typeof c&&!u.rootIdsByTypename[c]&&l.push({__typename:c});var h=new Set(r.selections);h.forEach(function(e){var r,p;if(td(e,s)){if(eQ(e)){var b=u.readField({fieldName:e.name.value,field:e,variables:o.variables,from:i},o),m=eX(e);void 0===b?nj.added(e)||(t=f.merge(t,((r={})[m]="Can't find field '".concat(e.name.value,"' on ").concat(eD(i)?i.__ref+" object":"object "+JSON.stringify(i,null,2)),r))):(0,tP.k)(b)?b=d(n.executeSubSelectedArray({field:e,array:b,enclosingRef:a,context:o}),m):e.selectionSet?null!=b&&(b=d(n.executeSelectionSet({selectionSet:e.selectionSet,objectOrReference:b,enclosingRef:eD(b)?b:a,context:o}),m)):o.canonizeResults&&(b=n.canon.pass(b)),void 0!==b&&l.push(((p={})[m]=b,p))}else{var g=eC(e,o.lookupFragment);if(!g&&e.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(e.name.value)):new Q.ej(5);g&&u.fragmentMatches(g,c)&&g.selectionSet.selections.forEach(h.add,h)}}});var p={result:tF(l),missing:t},b=o.canonizeResults?this.canon.admit(p):(0,iu.J)(p);return b.result&&this.knownResults.set(b.result,r),b},e.prototype.execSubSelectedArrayImpl=function(e){var t,n=this,r=e.field,i=e.array,a=e.enclosingRef,o=e.context,s=new tB;function u(e,n){var r;return e.missing&&(t=s.merge(t,((r={})[n]=e.missing,r))),e.result}return r.selectionSet&&(i=i.filter(o.store.canRead)),i=i.map(function(e,t){return null===e?null:(0,tP.k)(e)?u(n.executeSubSelectedArray({field:r,array:e,enclosingRef:a,context:o}),t):r.selectionSet?u(n.executeSelectionSet({selectionSet:r.selectionSet,objectOrReference:e,enclosingRef:eD(e)?e:a,context:o}),t):(__DEV__&&ij(o.store,r,e),e)}),{result:o.canonizeResults?this.canon.admit(i):i,missing:t}},e}();function iR(e){try{JSON.stringify(e,function(e,t){if("string"==typeof t)throw t;return t})}catch(t){return t}}function ij(e,t,n){if(!t.selectionSet){var r=new Set([n]);r.forEach(function(n){(0,eO.s)(n)&&(__DEV__?(0,Q.kG)(!eD(n),"Missing selection set for object of type ".concat(im(e,n)," returned for query field ").concat(t.name.value)):(0,Q.kG)(!eD(n),6),Object.values(n).forEach(r.add,r))})}}function iF(e){var t=nG("stringifyForDisplay");return JSON.stringify(e,function(e,n){return void 0===n?t:n}).split(JSON.stringify(t)).join("")}var iY=Object.create(null);function iB(e){var t=JSON.stringify(e);return iY[t]||(iY[t]=Object.create(null))}function iU(e){var t=iB(e);return t.keyFieldsFn||(t.keyFieldsFn=function(t,n){var r=function(e,t){return n.readField(t,e)},i=n.keyObject=i$(e,function(e){var i=iW(n.storeObject,e,r);return void 0===i&&t!==n.storeObject&&ic.call(t,e[0])&&(i=iW(t,e,iG)),__DEV__?(0,Q.kG)(void 0!==i,"Missing field '".concat(e.join("."),"' while extracting keyFields from ").concat(JSON.stringify(t))):(0,Q.kG)(void 0!==i,2),i});return"".concat(n.typename,":").concat(JSON.stringify(i))})}function iH(e){var t=iB(e);return t.keyArgsFn||(t.keyArgsFn=function(t,n){var r=n.field,i=n.variables,a=n.fieldName,o=JSON.stringify(i$(e,function(e){var n=e[0],a=n.charAt(0);if("@"===a){if(r&&(0,tP.O)(r.directives)){var o=n.slice(1),s=r.directives.find(function(e){return e.name.value===o}),u=s&&eZ(s,i);return u&&iW(u,e.slice(1))}return}if("$"===a){var c=n.slice(1);if(i&&ic.call(i,c)){var l=e.slice(0);return l[0]=c,iW(i,l)}return}if(t)return iW(t,e)}));return(t||"{}"!==o)&&(a+=":"+o),a})}function i$(e,t){var n=new tB;return iz(e).reduce(function(e,r){var i,a=t(r);if(void 0!==a){for(var o=r.length-1;o>=0;--o)a=((i={})[r[o]]=a,i);e=n.merge(e,a)}return e},Object.create(null))}function iz(e){var t=iB(e);if(!t.paths){var n=t.paths=[],r=[];e.forEach(function(t,i){(0,tP.k)(t)?(iz(t).forEach(function(e){return n.push(r.concat(e))}),r.length=0):(r.push(t),(0,tP.k)(e[i+1])||(n.push(r.slice(0)),r.length=0))})}return t.paths}function iG(e,t){return e[t]}function iW(e,t,n){return n=n||iG,iK(t.reduce(function e(t,r){return(0,tP.k)(t)?t.map(function(t){return e(t,r)}):t&&n(t,r)},e))}function iK(e){return(0,eO.s)(e)?(0,tP.k)(e)?e.map(iK):i$(Object.keys(e).sort(),function(t){return iW(e,t)}):e}function iV(e){return void 0!==e.args?e.args:e.field?eZ(e.field,e.variables):null}eK.setStringify(nx);var iq=function(){},iZ=function(e,t){return t.fieldName},iX=function(e,t,n){return(0,n.mergeObjects)(e,t)},iJ=function(e,t){return t},iQ=function(){function e(e){this.config=e,this.typePolicies=Object.create(null),this.toBeAdded=Object.create(null),this.supertypeMap=new Map,this.fuzzySubtypes=new Map,this.rootIdsByTypename=Object.create(null),this.rootTypenamesById=Object.create(null),this.usingPossibleTypes=!1,this.config=(0,en.pi)({dataIdFromObject:id},e),this.cache=this.config.cache,this.setRootTypename("Query"),this.setRootTypename("Mutation"),this.setRootTypename("Subscription"),e.possibleTypes&&this.addPossibleTypes(e.possibleTypes),e.typePolicies&&this.addTypePolicies(e.typePolicies)}return e.prototype.identify=function(e,t){var n,r,i=this,a=t&&(t.typename||(null===(n=t.storeObject)||void 0===n?void 0:n.__typename))||e.__typename;if(a===this.rootTypenamesById.ROOT_QUERY)return["ROOT_QUERY"];for(var o=t&&t.storeObject||e,s=(0,en.pi)((0,en.pi)({},t),{typename:a,storeObject:o,readField:t&&t.readField||function(){var e=i0(arguments,o);return i.readField(e,{store:i.cache.data,variables:e.variables})}}),u=a&&this.getTypePolicy(a),c=u&&u.keyFn||this.config.dataIdFromObject;c;){var l=c((0,en.pi)((0,en.pi)({},e),o),s);if((0,tP.k)(l))c=iU(l);else{r=l;break}}return r=r?String(r):void 0,s.keyObject?[r,s.keyObject]:[r]},e.prototype.addTypePolicies=function(e){var t=this;Object.keys(e).forEach(function(n){var r=e[n],i=r.queryType,a=r.mutationType,o=r.subscriptionType,s=(0,en._T)(r,["queryType","mutationType","subscriptionType"]);i&&t.setRootTypename("Query",n),a&&t.setRootTypename("Mutation",n),o&&t.setRootTypename("Subscription",n),ic.call(t.toBeAdded,n)?t.toBeAdded[n].push(s):t.toBeAdded[n]=[s]})},e.prototype.updateTypePolicy=function(e,t){var n=this,r=this.getTypePolicy(e),i=t.keyFields,a=t.fields;function o(e,t){e.merge="function"==typeof t?t:!0===t?iX:!1===t?iJ:e.merge}o(r,t.merge),r.keyFn=!1===i?iq:(0,tP.k)(i)?iU(i):"function"==typeof i?i:r.keyFn,a&&Object.keys(a).forEach(function(t){var r=n.getFieldPolicy(e,t,!0),i=a[t];if("function"==typeof i)r.read=i;else{var s=i.keyArgs,u=i.read,c=i.merge;r.keyFn=!1===s?iZ:(0,tP.k)(s)?iH(s):"function"==typeof s?s:r.keyFn,"function"==typeof u&&(r.read=u),o(r,c)}r.read&&r.merge&&(r.keyFn=r.keyFn||iZ)})},e.prototype.setRootTypename=function(e,t){void 0===t&&(t=e);var n="ROOT_"+e.toUpperCase(),r=this.rootTypenamesById[n];t!==r&&(__DEV__?(0,Q.kG)(!r||r===e,"Cannot change root ".concat(e," __typename more than once")):(0,Q.kG)(!r||r===e,3),r&&delete this.rootIdsByTypename[r],this.rootIdsByTypename[t]=n,this.rootTypenamesById[n]=t)},e.prototype.addPossibleTypes=function(e){var t=this;this.usingPossibleTypes=!0,Object.keys(e).forEach(function(n){t.getSupertypeSet(n,!0),e[n].forEach(function(e){t.getSupertypeSet(e,!0).add(n);var r=e.match(ig);r&&r[0]===e||t.fuzzySubtypes.set(e,RegExp(e))})})},e.prototype.getTypePolicy=function(e){var t=this;if(!ic.call(this.typePolicies,e)){var n=this.typePolicies[e]=Object.create(null);n.fields=Object.create(null);var r=this.supertypeMap.get(e);r&&r.size&&r.forEach(function(e){var r=t.getTypePolicy(e),i=r.fields;Object.assign(n,(0,en._T)(r,["fields"])),Object.assign(n.fields,i)})}var i=this.toBeAdded[e];return i&&i.length&&i.splice(0).forEach(function(n){t.updateTypePolicy(e,n)}),this.typePolicies[e]},e.prototype.getFieldPolicy=function(e,t,n){if(e){var r=this.getTypePolicy(e).fields;return r[t]||n&&(r[t]=Object.create(null))}},e.prototype.getSupertypeSet=function(e,t){var n=this.supertypeMap.get(e);return!n&&t&&this.supertypeMap.set(e,n=new Set),n},e.prototype.fragmentMatches=function(e,t,n,r){var i=this;if(!e.typeCondition)return!0;if(!t)return!1;var a=e.typeCondition.name.value;if(t===a)return!0;if(this.usingPossibleTypes&&this.supertypeMap.has(a))for(var o=this.getSupertypeSet(t,!0),s=[o],u=function(e){var t=i.getSupertypeSet(e,!1);t&&t.size&&0>s.indexOf(t)&&s.push(t)},c=!!(n&&this.fuzzySubtypes.size),l=!1,f=0;f1?a:t}:(r=(0,en.pi)({},i),ic.call(r,"from")||(r.from=t)),__DEV__&&void 0===r.from&&__DEV__&&Q.kG.warn("Undefined 'from' passed to readField with arguments ".concat(iF(Array.from(e)))),void 0===r.variables&&(r.variables=n),r}function i2(e){return function(t,n){if((0,tP.k)(t)||(0,tP.k)(n))throw __DEV__?new Q.ej("Cannot automatically merge arrays"):new Q.ej(4);if((0,eO.s)(t)&&(0,eO.s)(n)){var r=e.getFieldValue(t,"__typename"),i=e.getFieldValue(n,"__typename");if(r&&i&&r!==i)return n;if(eD(t)&&iw(n))return e.merge(t.__ref,n),t;if(iw(t)&&eD(n))return e.merge(t,n.__ref),n;if(iw(t)&&iw(n))return(0,en.pi)((0,en.pi)({},t),n)}return n}}function i3(e,t,n){var r="".concat(t).concat(n),i=e.flavors.get(r);return i||e.flavors.set(r,i=e.clientOnly===t&&e.deferred===n?e:(0,en.pi)((0,en.pi)({},e),{clientOnly:t,deferred:n})),i}var i4=function(){function e(e,t,n){this.cache=e,this.reader=t,this.fragments=n}return e.prototype.writeToStore=function(e,t){var n=this,r=t.query,i=t.result,a=t.dataId,o=t.variables,s=t.overwrite,u=e2(r),c=i_();o=(0,en.pi)((0,en.pi)({},e8(u)),o);var l=(0,en.pi)((0,en.pi)({store:e,written:Object.create(null),merge:function(e,t){return c.merge(e,t)},variables:o,varString:nx(o)},iE(r,this.fragments)),{overwrite:!!s,incomingById:new Map,clientOnly:!1,deferred:!1,flavors:new Map}),f=this.processSelectionSet({result:i||Object.create(null),dataId:a,selectionSet:u.selectionSet,mergeTree:{map:new Map},context:l});if(!eD(f))throw __DEV__?new Q.ej("Could not identify object ".concat(JSON.stringify(i))):new Q.ej(7);return l.incomingById.forEach(function(t,r){var i=t.storeObject,a=t.mergeTree,o=t.fieldNodeSet,s=eI(r);if(a&&a.map.size){var u=n.applyMerges(a,s,i,l);if(eD(u))return;i=u}if(__DEV__&&!l.overwrite){var c=Object.create(null);o.forEach(function(e){e.selectionSet&&(c[e.name.value]=!0)});var f=function(e){return!0===c[iv(e)]},d=function(e){var t=a&&a.map.get(e);return Boolean(t&&t.info&&t.info.merge)};Object.keys(i).forEach(function(e){f(e)&&!d(e)&&at(s,i,e,l.store)})}e.merge(r,i)}),e.retain(f.__ref),f},e.prototype.processSelectionSet=function(e){var t=this,n=e.dataId,r=e.result,i=e.selectionSet,a=e.context,o=e.mergeTree,s=this.cache.policies,u=Object.create(null),c=n&&s.rootTypenamesById[n]||eJ(r,i,a.fragmentMap)||n&&a.store.get(n,"__typename");"string"==typeof c&&(u.__typename=c);var l=function(){var e=i0(arguments,u,a.variables);if(eD(e.from)){var t=a.incomingById.get(e.from.__ref);if(t){var n=s.readField((0,en.pi)((0,en.pi)({},e),{from:t.storeObject}),a);if(void 0!==n)return n}}return s.readField(e,a)},f=new Set;this.flattenFields(i,r,a,c).forEach(function(e,n){var i,a=r[eX(n)];if(f.add(n),void 0!==a){var d=s.getStoreFieldName({typename:c,fieldName:n.name.value,field:n,variables:e.variables}),h=i6(o,d),p=t.processFieldValue(a,n,n.selectionSet?i3(e,!1,!1):e,h),b=void 0;n.selectionSet&&(eD(p)||iw(p))&&(b=l("__typename",p));var m=s.getMergeFunction(c,n.name.value,b);m?h.info={field:n,typename:c,merge:m}:i7(o,d),u=e.merge(u,((i={})[d]=p,i))}else __DEV__&&!e.clientOnly&&!e.deferred&&!nj.added(n)&&!s.getReadFunction(c,n.name.value)&&__DEV__&&Q.kG.error("Missing field '".concat(eX(n),"' while writing result ").concat(JSON.stringify(r,null,2)).substring(0,1e3))});try{var d=s.identify(r,{typename:c,selectionSet:i,fragmentMap:a.fragmentMap,storeObject:u,readField:l}),h=d[0],p=d[1];n=n||h,p&&(u=a.merge(u,p))}catch(b){if(!n)throw b}if("string"==typeof n){var m=eI(n),g=a.written[n]||(a.written[n]=[]);if(g.indexOf(i)>=0||(g.push(i),this.reader&&this.reader.isFresh(r,m,i,a)))return m;var v=a.incomingById.get(n);return v?(v.storeObject=a.merge(v.storeObject,u),v.mergeTree=i9(v.mergeTree,o),f.forEach(function(e){return v.fieldNodeSet.add(e)})):a.incomingById.set(n,{storeObject:u,mergeTree:i8(o)?void 0:o,fieldNodeSet:f}),m}return u},e.prototype.processFieldValue=function(e,t,n,r){var i=this;return t.selectionSet&&null!==e?(0,tP.k)(e)?e.map(function(e,a){var o=i.processFieldValue(e,t,n,i6(r,a));return i7(r,a),o}):this.processSelectionSet({result:e,selectionSet:t.selectionSet,context:n,mergeTree:r}):__DEV__?nJ(e):e},e.prototype.flattenFields=function(e,t,n,r){void 0===r&&(r=eJ(t,e,n.fragmentMap));var i=new Map,a=this.cache.policies,o=new n_(!1);return function e(s,u){var c=o.lookup(s,u.clientOnly,u.deferred);c.visited||(c.visited=!0,s.selections.forEach(function(o){if(td(o,n.variables)){var s=u.clientOnly,c=u.deferred;if(!(s&&c)&&(0,tP.O)(o.directives)&&o.directives.forEach(function(e){var t=e.name.value;if("client"===t&&(s=!0),"defer"===t){var r=eZ(e,n.variables);r&&!1===r.if||(c=!0)}}),eQ(o)){var l=i.get(o);l&&(s=s&&l.clientOnly,c=c&&l.deferred),i.set(o,i3(n,s,c))}else{var f=eC(o,n.lookupFragment);if(!f&&o.kind===nL.h.FRAGMENT_SPREAD)throw __DEV__?new Q.ej("No fragment named ".concat(o.name.value)):new Q.ej(8);f&&a.fragmentMatches(f,r,t,n.variables)&&e(f.selectionSet,i3(n,s,c))}}}))}(e,n),i},e.prototype.applyMerges=function(e,t,n,r,i){var a=this;if(e.map.size&&!eD(n)){var o,s,u=!(0,tP.k)(n)&&(eD(t)||iw(t))?t:void 0,c=n;u&&!i&&(i=[eD(u)?u.__ref:u]);var l=function(e,t){return(0,tP.k)(e)?"number"==typeof t?e[t]:void 0:r.store.getFieldValue(e,String(t))};e.map.forEach(function(e,t){var n=l(u,t),o=l(c,t);if(void 0!==o){i&&i.push(t);var f=a.applyMerges(e,n,o,r,i);f!==o&&(s=s||new Map).set(t,f),i&&(0,Q.kG)(i.pop()===t)}}),s&&(n=(0,tP.k)(c)?c.slice(0):(0,en.pi)({},c),s.forEach(function(e,t){n[t]=e}))}return e.info?this.cache.policies.runMergeFunction(t,n,e.info,r,i&&(o=r.store).getStorage.apply(o,i)):n},e}(),i5=[];function i6(e,t){var n=e.map;return n.has(t)||n.set(t,i5.pop()||{map:new Map}),n.get(t)}function i9(e,t){if(e===t||!t||i8(t))return e;if(!e||i8(e))return t;var n=e.info&&t.info?(0,en.pi)((0,en.pi)({},e.info),t.info):e.info||t.info,r=e.map.size&&t.map.size,i=r?new Map:e.map.size?e.map:t.map,a={info:n,map:i};if(r){var o=new Set(t.map.keys());e.map.forEach(function(e,n){a.map.set(n,i9(e,t.map.get(n))),o.delete(n)}),o.forEach(function(n){a.map.set(n,i9(t.map.get(n),e.map.get(n)))})}return a}function i8(e){return!e||!(e.info||e.map.size)}function i7(e,t){var n=e.map,r=n.get(t);r&&i8(r)&&(i5.push(r),n.delete(t))}var ae=new Set;function at(e,t,n,r){var i=function(e){var t=r.getFieldValue(e,n);return"object"==typeof t&&t},a=i(e);if(a){var o=i(t);if(!(!o||eD(a)||(0,nm.D)(a,o)||Object.keys(a).every(function(e){return void 0!==r.getFieldValue(o,e)}))){var s=r.getFieldValue(e,"__typename")||r.getFieldValue(t,"__typename"),u=iv(n),c="".concat(s,".").concat(u);if(!ae.has(c)){ae.add(c);var l=[];(0,tP.k)(a)||(0,tP.k)(o)||[a,o].forEach(function(e){var t=r.getFieldValue(e,"__typename");"string"!=typeof t||l.includes(t)||l.push(t)}),__DEV__&&Q.kG.warn("Cache data may be lost when replacing the ".concat(u," field of a ").concat(s," object.\n\nThis could cause additional (usually avoidable) network requests to fetch data that were otherwise cached.\n\nTo address this problem (which is not a bug in Apollo Client), ").concat(l.length?"either ensure all objects of type "+l.join(" and ")+" have an ID or a custom merge function, or ":"","define a custom merge function for the ").concat(c," field, so InMemoryCache can safely merge these objects:\n\n existing: ").concat(JSON.stringify(a).slice(0,1e3),"\n incoming: ").concat(JSON.stringify(o).slice(0,1e3),"\n\nFor more information about these options, please refer to the documentation:\n\n * Ensuring entity objects have IDs: https://go.apollo.dev/c/generating-unique-identifiers\n * Defining custom merge functions: https://go.apollo.dev/c/merging-non-normalized-objects\n"))}}}}var an=function(e){function t(t){void 0===t&&(t={});var n=e.call(this)||this;return n.watches=new Set,n.typenameDocumentCache=new Map,n.makeVar=r2,n.txCount=0,n.config=ip(t),n.addTypename=!!n.config.addTypename,n.policies=new iQ({cache:n,dataIdFromObject:n.config.dataIdFromObject,possibleTypes:n.config.possibleTypes,typePolicies:n.config.typePolicies}),n.init(),n}return(0,en.ZT)(t,e),t.prototype.init=function(){var e=this.data=new iT.Root({policies:this.policies,resultCaching:this.config.resultCaching});this.optimisticData=e.stump,this.resetResultCache()},t.prototype.resetResultCache=function(e){var t=this,n=this.storeReader,r=this.config.fragments;this.storeWriter=new i4(this,this.storeReader=new iP({cache:this,addTypename:this.addTypename,resultCacheMaxSize:this.config.resultCacheMaxSize,canonizeResults:ib(this.config),canon:e?void 0:n&&n.canon,fragments:r}),r),this.maybeBroadcastWatch=rZ(function(e,n){return t.broadcastWatch(e,n)},{max:this.config.resultCacheMaxSize,makeCacheKey:function(e){var n=e.optimistic?t.optimisticData:t.data;if(iD(n)){var r=e.optimistic,i=e.id,a=e.variables;return n.makeCacheKey(e.query,e.callback,nx({optimistic:r,id:i,variables:a}))}}}),new Set([this.data.group,this.optimisticData.group,]).forEach(function(e){return e.resetCaching()})},t.prototype.restore=function(e){return this.init(),e&&this.data.replace(e),this},t.prototype.extract=function(e){return void 0===e&&(e=!1),(e?this.optimisticData:this.data).extract()},t.prototype.read=function(e){var t=e.returnPartialData,n=void 0!==t&&t;try{return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,config:this.config,returnPartialData:n})).result||null}catch(r){if(r instanceof is)return null;throw r}},t.prototype.write=function(e){try{return++this.txCount,this.storeWriter.writeToStore(this.data,e)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.modify=function(e){if(ic.call(e,"id")&&!e.id)return!1;var t=e.optimistic?this.optimisticData:this.data;try{return++this.txCount,t.modify(e.id||"ROOT_QUERY",e.fields)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.diff=function(e){return this.storeReader.diffQueryAgainstStore((0,en.pi)((0,en.pi)({},e),{store:e.optimistic?this.optimisticData:this.data,rootId:e.id||"ROOT_QUERY",config:this.config}))},t.prototype.watch=function(e){var t=this;return this.watches.size||r0(this),this.watches.add(e),e.immediate&&this.maybeBroadcastWatch(e),function(){t.watches.delete(e)&&!t.watches.size&&r1(t),t.maybeBroadcastWatch.forget(e)}},t.prototype.gc=function(e){nx.reset();var t=this.optimisticData.gc();return e&&!this.txCount&&(e.resetResultCache?this.resetResultCache(e.resetResultIdentities):e.resetResultIdentities&&this.storeReader.resetCanon()),t},t.prototype.retain=function(e,t){return(t?this.optimisticData:this.data).retain(e)},t.prototype.release=function(e,t){return(t?this.optimisticData:this.data).release(e)},t.prototype.identify=function(e){if(eD(e))return e.__ref;try{return this.policies.identify(e)[0]}catch(t){__DEV__&&Q.kG.warn(t)}},t.prototype.evict=function(e){if(!e.id){if(ic.call(e,"id"))return!1;e=(0,en.pi)((0,en.pi)({},e),{id:"ROOT_QUERY"})}try{return++this.txCount,this.optimisticData.evict(e,this.data)}finally{--this.txCount||!1===e.broadcast||this.broadcastWatches()}},t.prototype.reset=function(e){var t=this;return this.init(),nx.reset(),e&&e.discardWatches?(this.watches.forEach(function(e){return t.maybeBroadcastWatch.forget(e)}),this.watches.clear(),r1(this)):this.broadcastWatches(),Promise.resolve()},t.prototype.removeOptimistic=function(e){var t=this.optimisticData.removeLayer(e);t!==this.optimisticData&&(this.optimisticData=t,this.broadcastWatches())},t.prototype.batch=function(e){var t,n=this,r=e.update,i=e.optimistic,a=void 0===i||i,o=e.removeOptimistic,s=e.onWatchUpdated,u=function(e){var i=n,a=i.data,o=i.optimisticData;++n.txCount,e&&(n.data=n.optimisticData=e);try{return t=r(n)}finally{--n.txCount,n.data=a,n.optimisticData=o}},c=new Set;return s&&!this.txCount&&this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e){return c.add(e),!1}})),"string"==typeof a?this.optimisticData=this.optimisticData.addLayer(a,u):!1===a?u(this.data):u(),"string"==typeof o&&(this.optimisticData=this.optimisticData.removeLayer(o)),s&&c.size?(this.broadcastWatches((0,en.pi)((0,en.pi)({},e),{onWatchUpdated:function(e,t){var n=s.call(this,e,t);return!1!==n&&c.delete(e),n}})),c.size&&c.forEach(function(e){return n.maybeBroadcastWatch.dirty(e)})):this.broadcastWatches(e),t},t.prototype.performTransaction=function(e,t){return this.batch({update:e,optimistic:t||null!==t})},t.prototype.transformDocument=function(e){if(this.addTypename){var t=this.typenameDocumentCache.get(e);return t||(t=nj(e),this.typenameDocumentCache.set(e,t),this.typenameDocumentCache.set(t,t)),t}return e},t.prototype.transformForLink=function(e){var t=this.config.fragments;return t?t.transform(e):e},t.prototype.broadcastWatches=function(e){var t=this;this.txCount||this.watches.forEach(function(n){return t.maybeBroadcastWatch(n,e)})},t.prototype.broadcastWatch=function(e,t){var n=e.lastDiff,r=this.diff(e);(!t||(e.optimistic&&"string"==typeof t.optimistic&&(r.fromOptimisticTransaction=!0),!t.onWatchUpdated||!1!==t.onWatchUpdated.call(this,e,r,n)))&&(n&&(0,nm.D)(n.result,r.result)||e.callback(e.lastDiff=r,n))},t}(io),ar={possibleTypes:{ApproveJobProposalSpecPayload:["ApproveJobProposalSpecSuccess","JobAlreadyExistsError","NotFoundError"],BridgePayload:["Bridge","NotFoundError"],CancelJobProposalSpecPayload:["CancelJobProposalSpecSuccess","NotFoundError"],ChainPayload:["Chain","NotFoundError"],CreateAPITokenPayload:["CreateAPITokenSuccess","InputErrors"],CreateBridgePayload:["CreateBridgeSuccess"],CreateCSAKeyPayload:["CSAKeyExistsError","CreateCSAKeySuccess"],CreateFeedsManagerChainConfigPayload:["CreateFeedsManagerChainConfigSuccess","InputErrors","NotFoundError"],CreateFeedsManagerPayload:["CreateFeedsManagerSuccess","InputErrors","NotFoundError","SingleFeedsManagerError"],CreateJobPayload:["CreateJobSuccess","InputErrors"],CreateOCR2KeyBundlePayload:["CreateOCR2KeyBundleSuccess"],CreateOCRKeyBundlePayload:["CreateOCRKeyBundleSuccess"],CreateP2PKeyPayload:["CreateP2PKeySuccess"],DeleteAPITokenPayload:["DeleteAPITokenSuccess","InputErrors"],DeleteBridgePayload:["DeleteBridgeConflictError","DeleteBridgeInvalidNameError","DeleteBridgeSuccess","NotFoundError"],DeleteCSAKeyPayload:["DeleteCSAKeySuccess","NotFoundError"],DeleteFeedsManagerChainConfigPayload:["DeleteFeedsManagerChainConfigSuccess","NotFoundError"],DeleteJobPayload:["DeleteJobSuccess","NotFoundError"],DeleteOCR2KeyBundlePayload:["DeleteOCR2KeyBundleSuccess","NotFoundError"],DeleteOCRKeyBundlePayload:["DeleteOCRKeyBundleSuccess","NotFoundError"],DeleteP2PKeyPayload:["DeleteP2PKeySuccess","NotFoundError"],DeleteVRFKeyPayload:["DeleteVRFKeySuccess","NotFoundError"],DismissJobErrorPayload:["DismissJobErrorSuccess","NotFoundError"],Error:["CSAKeyExistsError","DeleteBridgeConflictError","DeleteBridgeInvalidNameError","InputError","JobAlreadyExistsError","NotFoundError","RunJobCannotRunError","SingleFeedsManagerError"],EthTransactionPayload:["EthTransaction","NotFoundError"],FeaturesPayload:["Features"],FeedsManagerPayload:["FeedsManager","NotFoundError"],GetSQLLoggingPayload:["SQLLogging"],GlobalLogLevelPayload:["GlobalLogLevel"],JobPayload:["Job","NotFoundError"],JobProposalPayload:["JobProposal","NotFoundError"],JobRunPayload:["JobRun","NotFoundError"],JobSpec:["BlockHeaderFeederSpec","BlockhashStoreSpec","BootstrapSpec","CronSpec","DirectRequestSpec","FluxMonitorSpec","GatewaySpec","KeeperSpec","OCR2Spec","OCRSpec","VRFSpec","WebhookSpec"],NodePayload:["Node","NotFoundError"],PaginatedPayload:["BridgesPayload","ChainsPayload","EthTransactionAttemptsPayload","EthTransactionsPayload","JobRunsPayload","JobsPayload","NodesPayload"],RejectJobProposalSpecPayload:["NotFoundError","RejectJobProposalSpecSuccess"],RunJobPayload:["NotFoundError","RunJobCannotRunError","RunJobSuccess"],SetGlobalLogLevelPayload:["InputErrors","SetGlobalLogLevelSuccess"],SetSQLLoggingPayload:["SetSQLLoggingSuccess"],SetServicesLogLevelsPayload:["InputErrors","SetServicesLogLevelsSuccess"],UpdateBridgePayload:["NotFoundError","UpdateBridgeSuccess"],UpdateFeedsManagerChainConfigPayload:["InputErrors","NotFoundError","UpdateFeedsManagerChainConfigSuccess"],UpdateFeedsManagerPayload:["InputErrors","NotFoundError","UpdateFeedsManagerSuccess"],UpdateJobProposalSpecDefinitionPayload:["NotFoundError","UpdateJobProposalSpecDefinitionSuccess"],UpdatePasswordPayload:["InputErrors","UpdatePasswordSuccess"],VRFKeyPayload:["NotFoundError","VRFKeySuccess"]}};let ai=ar;var aa=(r=void 0,location.origin),ao=new nh({uri:"".concat(aa,"/query"),credentials:"include"}),as=new ia({cache:new an({possibleTypes:ai.possibleTypes}),link:ao});if(a.Z.locale(o),u().defaultFormat="YYYY-MM-DD h:mm:ss A","undefined"!=typeof document){var au,ac,al=f().hydrate;ac=X,al(c.createElement(et,{client:as},c.createElement(d.zj,null,c.createElement(i.MuiThemeProvider,{theme:J.r},c.createElement(ac,null)))),document.getElementById("root"))}})()})(); \ No newline at end of file diff --git a/core/web/assets/main.f42e73c0c7811e9907db.js.gz b/core/web/assets/main.50e70a50a20fd1cb616f.js.gz similarity index 94% rename from core/web/assets/main.f42e73c0c7811e9907db.js.gz rename to core/web/assets/main.50e70a50a20fd1cb616f.js.gz index 408214985c1..da45571a37c 100644 Binary files a/core/web/assets/main.f42e73c0c7811e9907db.js.gz and b/core/web/assets/main.50e70a50a20fd1cb616f.js.gz differ diff --git a/core/web/resolver/testdata/config-full.toml b/core/web/resolver/testdata/config-full.toml index 3e4f2539943..4eb2fce6c47 100644 --- a/core/web/resolver/testdata/config-full.toml +++ b/core/web/resolver/testdata/config-full.toml @@ -341,6 +341,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 13 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 11 @@ -429,6 +430,7 @@ URL = 'http://solana.bar' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' Enabled = true OCR2CachePollPeriod = '6h0m0s' OCR2CacheTTL = '3m0s' @@ -439,3 +441,4 @@ ConfirmationPoll = '42s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/core/web/resolver/testdata/config-multi-chain-effective.toml b/core/web/resolver/testdata/config-multi-chain-effective.toml index 7e4e6e44d2e..67cd1770d97 100644 --- a/core/web/resolver/testdata/config-multi-chain-effective.toml +++ b/core/web/resolver/testdata/config-multi-chain-effective.toml @@ -313,6 +313,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -403,6 +404,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -487,6 +489,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 @@ -586,6 +589,7 @@ URL = 'http://testnet.solana.com' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' OCR2CachePollPeriod = '5s' OCR2CacheTTL = '1m0s' RequestTimeout = '10s' @@ -595,3 +599,4 @@ ConfirmationPoll = '1h0m0s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/core/web/resolver/testdata/config-multi-chain.toml b/core/web/resolver/testdata/config-multi-chain.toml index 543fb3156bd..7180471ca2a 100644 --- a/core/web/resolver/testdata/config-multi-chain.toml +++ b/core/web/resolver/testdata/config-multi-chain.toml @@ -107,8 +107,10 @@ URL = 'http://testnet.solana.com' [[Starknet]] ChainID = 'foobar' +FeederURL = 'http://feeder.url' ConfirmationPoll = '1h0m0s' [[Starknet.Nodes]] Name = 'primary' URL = 'http://stark.node' +APIKey = 'key' diff --git a/docs/CONFIG.md b/docs/CONFIG.md index 2b7620a3c7c..9e385acd750 100644 --- a/docs/CONFIG.md +++ b/docs/CONFIG.md @@ -1770,6 +1770,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -1854,6 +1855,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -1938,6 +1940,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2022,6 +2025,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2107,6 +2111,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -2191,6 +2196,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2275,6 +2281,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2360,6 +2367,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2444,6 +2452,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2527,6 +2536,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2610,6 +2620,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2694,6 +2705,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2779,6 +2791,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2863,6 +2876,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -2947,6 +2961,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -3031,6 +3046,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -3115,6 +3131,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3199,6 +3216,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -3283,6 +3301,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -3367,6 +3386,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -3452,6 +3472,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3536,6 +3557,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3619,6 +3641,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3703,6 +3726,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3786,6 +3810,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3870,6 +3895,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -3954,6 +3980,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4037,6 +4064,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4120,6 +4148,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4204,6 +4233,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4287,6 +4317,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4371,6 +4402,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -4454,6 +4486,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4538,6 +4571,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4622,6 +4656,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -4707,6 +4742,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4791,6 +4827,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4875,6 +4912,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -4959,6 +4997,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5043,6 +5082,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5126,6 +5166,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -5209,6 +5250,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -5293,6 +5335,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -5377,6 +5420,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5461,6 +5505,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5546,6 +5591,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5631,6 +5677,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5715,6 +5762,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5799,6 +5847,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5883,6 +5932,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -5967,6 +6017,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -6051,6 +6102,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 10 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 1 @@ -6135,6 +6187,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -6219,6 +6272,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [OCR] ContractConfirmations = 4 @@ -6863,6 +6917,7 @@ SelectionMode = 'HighestHead' # Default SyncThreshold = 5 # Default LeaseDuration = '0s' # Default NodeIsSyncingEnabled = false # Default +FinalizedBlockPollInterval = '5s' # Default ``` The node pool manages multiple RPC endpoints. @@ -6924,6 +6979,18 @@ All of the requests to node in state `Syncing` are rejected. Set true to enable this check +### FinalizedBlockPollInterval +```toml +FinalizedBlockPollInterval = '5s' # Default +``` +FinalizedBlockPollInterval controls how often to poll RPC for new finalized blocks. +The finalized block is only used to report to the `pool_rpc_node_highest_finalized_block` metric. We plan to use it +in RPCs health assessment in the future. +If `FinalityTagEnabled = false`, poll is not performed and `pool_rpc_node_highest_finalized_block` is +reported based on latest block and finality depth. + +Set to 0 to disable. + ## EVM.OCR ```toml [EVM.OCR] @@ -7317,6 +7384,7 @@ URL is the HTTP(S) endpoint for this node. ```toml [[Starknet]] ChainID = 'foobar' # Example +FeederURL = 'http://feeder.url' # Example Enabled = true # Default OCR2CachePollPeriod = '5s' # Default OCR2CacheTTL = '1m' # Default @@ -7332,6 +7400,12 @@ ChainID = 'foobar' # Example ``` ChainID is the Starknet chain ID. +### FeederURL +```toml +FeederURL = 'http://feeder.url' # Example +``` +FeederURL is required to get tx metadata (that the RPC can't) + ### Enabled ```toml Enabled = true # Default @@ -7373,6 +7447,7 @@ ConfirmationPoll is how often to confirmer checks for tx inclusion on chain. [[Starknet.Nodes]] Name = 'primary' # Example URL = 'http://stark.node' # Example +APIKey = 'key' # Example ``` @@ -7388,3 +7463,9 @@ URL = 'http://stark.node' # Example ``` URL is the base HTTP(S) endpoint for this node. +### APIKey +```toml +APIKey = 'key' # Example +``` +APIKey Header is optional and only required for Nethermind RPCs + diff --git a/go.md b/go.md index 497f87d77b5..dd17f5207bd 100644 --- a/go.md +++ b/go.md @@ -20,8 +20,6 @@ flowchart LR classDef outline stroke-dasharray:6,fill:none; class chains,products outline - chainlink/v2 --> caigo - click caigo href "https://github.com/smartcontractkit/caigo" chainlink/v2 --> chain-selectors click chain-selectors href "https://github.com/smartcontractkit/chain-selectors" chainlink/v2 --> chainlink-automation @@ -60,7 +58,6 @@ flowchart LR chainlink-feeds --> libocr chainlink-solana --> chainlink-common chainlink-solana --> libocr - chainlink-starknet/relayer --> caigo chainlink-starknet/relayer --> chainlink-common chainlink-starknet/relayer --> libocr chainlink-vrf --> libocr diff --git a/go.mod b/go.mod index 152b50d0a8b..2df9c7ea4f0 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,8 @@ require ( github.com/Depado/ginprom v1.8.0 github.com/Masterminds/semver/v3 v3.2.1 github.com/Masterminds/sprig/v3 v3.2.3 + github.com/NethermindEth/juno v0.3.1 + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 github.com/XSAM/otelsql v0.27.0 github.com/avast/retry-go/v4 v4.5.1 github.com/btcsuite/btcd/btcec/v2 v2.3.2 @@ -68,7 +70,6 @@ require ( github.com/scylladb/go-reflectx v1.0.1 github.com/shirou/gopsutil/v3 v3.23.11 github.com/shopspring/decimal v1.3.1 - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 github.com/smartcontractkit/chain-selectors v1.0.10 github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240324144450-2bc22a6738ac @@ -76,9 +77,9 @@ require ( 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 - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 - github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 + 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 @@ -110,7 +111,14 @@ require ( google.golang.org/protobuf v1.33.0 gopkg.in/guregu/null.v4 v4.0.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 - gopkg.in/yaml.v3 v3.0.1 +) + +require ( + github.com/bahlo/generic-list-go v0.2.0 // indirect + github.com/buger/jsonparser v1.1.1 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( @@ -208,8 +216,7 @@ require ( github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.2 // indirect - github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect + github.com/google/go-cmp v0.6.0 github.com/google/go-tpm v0.9.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/gorilla/context v1.1.1 // indirect @@ -236,6 +243,7 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgio v1.0.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -277,6 +285,7 @@ require ( github.com/rivo/uniseg v0.4.4 // indirect github.com/rs/zerolog v1.30.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/sethvargo/go-retry v0.2.4 // indirect github.com/shirou/gopsutil v3.21.11+incompatible // indirect @@ -294,6 +303,7 @@ require ( github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/teris-io/shortid v0.0.0-20201117134242-e59966efd125 // indirect + github.com/test-go/testify v1.1.4 // indirect github.com/tidwall/btree v1.6.0 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect @@ -333,7 +343,7 @@ require ( nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v0.5.5 // indirect rsc.io/tmplfunc v0.0.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 ) replace ( diff --git a/go.sum b/go.sum index 9d0054974a0..8fb3d4c26d4 100644 --- a/go.sum +++ b/go.sum @@ -113,6 +113,10 @@ github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -159,6 +163,8 @@ github.com/aws/aws-sdk-go v1.45.25/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8P github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= 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= @@ -185,6 +191,7 @@ github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3 h1:SDlJ7bAm4ewvrmZtR0DaiYbQGd github.com/btcsuite/btcd/chaincfg/chainhash v1.0.3/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= @@ -590,8 +597,6 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-tpm v0.9.0 h1:sQF6YqWMi+SCXpsmS3fd21oPy/vSddwZry4JnmltHVk= github.com/google/go-tpm v0.9.0/go.mod h1:FkNVkc6C+IsvDI9Jw1OveJmxGZUUaKxtrpOS47QWKfU= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -762,6 +767,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/+fafWORmlnuysV2EMP8MW+qe0= github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= @@ -838,6 +845,7 @@ github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwA github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -910,6 +918,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= github.com/manyminds/api2go v0.0.0-20171030193247-e7b693844a6f h1:tVvGiZQFjOXP+9YyGqSA6jE55x1XVxmoPYudncxrZ8U= @@ -1138,6 +1148,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1166,8 +1178,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= @@ -1182,16 +1192,16 @@ github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e h1:k8HS3GsAFZnxXIW3141VsQP2+EL1XrTtOi/HDt7sdBE= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e/go.mod h1:JiykN+8W5TA4UD2ClrzQCVvcH3NcyLEVv7RwY0busrw= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +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/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= @@ -1318,6 +1328,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vertica/vertica-sql-go v1.3.3 h1:fL+FKEAEy5ONmsvya2WH5T8bhkvY27y/Ik3ReR2T+Qw= github.com/vertica/vertica-sql-go v1.3.3/go.mod h1:jnn2GFuv+O2Jcjktb7zyc4Utlbu9YVqpHH/lx63+1M4= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1988,5 +2000,5 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/integration-tests/actions/vrf/common/actions.go b/integration-tests/actions/vrf/common/actions.go index 22a2bd415f4..4af9fd05572 100644 --- a/integration-tests/actions/vrf/common/actions.go +++ b/integration-tests/actions/vrf/common/actions.go @@ -146,6 +146,86 @@ func CreateBHSJob( return job, nil } +func SetupBHFNode( + env *test_env.CLClusterTestEnv, + config *vrf_common_config.General, + numberOfTxKeysToCreate int, + chainID *big.Int, + coordinatorAddress string, + BHSAddress string, + batchBHSAddress string, + txKeyFunding float64, + l zerolog.Logger, + bhfNode *VRFNode, +) error { + evmClient, err := env.GetEVMClient(chainID.Int64()) + if err != nil { + return err + } + bhfTXKeyAddressStrings, _, err := CreateFundAndGetSendingKeys( + evmClient, + bhfNode, + txKeyFunding, + numberOfTxKeysToCreate, + chainID, + ) + if err != nil { + return err + } + bhfNode.TXKeyAddressStrings = bhfTXKeyAddressStrings + bhfSpec := client.BlockHeaderFeederJobSpec{ + ForwardingAllowed: false, + CoordinatorV2Address: coordinatorAddress, + CoordinatorV2PlusAddress: coordinatorAddress, + BlockhashStoreAddress: BHSAddress, + BatchBlockhashStoreAddress: batchBHSAddress, + FromAddresses: bhfTXKeyAddressStrings, + EVMChainID: chainID.String(), + WaitBlocks: *config.BHFJobWaitBlocks, + LookbackBlocks: *config.BHFJobLookBackBlocks, + PollPeriod: config.BHFJobPollPeriod.Duration, + RunTimeout: config.BHFJobRunTimeout.Duration, + } + l.Info().Msg("Creating BHF Job") + bhfJob, err := CreateBHFJob( + bhfNode.CLNode.API, + bhfSpec, + ) + if err != nil { + return fmt.Errorf("%s, err %w", "", err) + } + bhfNode.Job = bhfJob + return nil +} + +func CreateBHFJob( + chainlinkNode *client.ChainlinkClient, + bhfJobSpecConfig client.BlockHeaderFeederJobSpec, +) (*client.Job, error) { + jobUUID := uuid.New() + spec := &client.BlockHeaderFeederJobSpec{ + Name: fmt.Sprintf("bhf-%s", jobUUID), + ForwardingAllowed: bhfJobSpecConfig.ForwardingAllowed, + CoordinatorV2Address: bhfJobSpecConfig.CoordinatorV2Address, + CoordinatorV2PlusAddress: bhfJobSpecConfig.CoordinatorV2PlusAddress, + BlockhashStoreAddress: bhfJobSpecConfig.BlockhashStoreAddress, + BatchBlockhashStoreAddress: bhfJobSpecConfig.BatchBlockhashStoreAddress, + FromAddresses: bhfJobSpecConfig.FromAddresses, + EVMChainID: bhfJobSpecConfig.EVMChainID, + ExternalJobID: jobUUID.String(), + WaitBlocks: bhfJobSpecConfig.WaitBlocks, + LookbackBlocks: bhfJobSpecConfig.LookbackBlocks, + PollPeriod: bhfJobSpecConfig.PollPeriod, + RunTimeout: bhfJobSpecConfig.RunTimeout, + } + + job, err := chainlinkNode.MustCreateJob(spec) + if err != nil { + return nil, fmt.Errorf("%s, err %w", ErrCreatingBHSJob, err) + } + return job, nil +} + func WaitForRequestCountEqualToFulfilmentCount( ctx context.Context, consumer VRFLoadTestConsumer, diff --git a/integration-tests/actions/vrf/common/errors.go b/integration-tests/actions/vrf/common/errors.go index ba852a4c555..287403ecfdf 100644 --- a/integration-tests/actions/vrf/common/errors.go +++ b/integration-tests/actions/vrf/common/errors.go @@ -1,27 +1,28 @@ package common const ( - ErrNodePrimaryKey = "error getting node's primary ETH key" - ErrNodeNewTxKey = "error creating node's EVM transaction key" - ErrCreatingProvingKeyHash = "error creating a keyHash from the proving key" - ErrRegisteringProvingKey = "error registering a proving key on Coordinator contract" - ErrRegisterProvingKey = "error registering proving keys" - ErrEncodingProvingKey = "error encoding proving key" - ErrDeployBlockHashStore = "error deploying blockhash store" - ErrDeployCoordinator = "error deploying VRF CoordinatorV2" - ErrABIEncodingFunding = "error Abi encoding subscriptionID" - ErrSendingLinkToken = "error sending Link token" - ErrCreatingBHSJob = "error creating BHS job" - ErrParseJob = "error parsing job definition" - ErrSetVRFCoordinatorConfig = "error setting config for VRF Coordinator contract" - ErrCreateVRFSubscription = "error creating VRF Subscription" - ErrAddConsumerToSub = "error adding consumer to VRF Subscription" - ErrFundSubWithLinkToken = "error funding subscription with Link tokens" - ErrRestartCLNode = "error restarting CL node" - ErrWaitTXsComplete = "error waiting for TXs to complete" - ErrRequestRandomness = "error requesting randomness" - ErrLoadingCoordinator = "error loading coordinator contract" - ErrCreatingVRFKey = "error creating VRF key" + ErrNodePrimaryKey = "error getting node's primary ETH key" + ErrNodeNewTxKey = "error creating node's EVM transaction key" + ErrCreatingProvingKeyHash = "error creating a keyHash from the proving key" + ErrRegisteringProvingKey = "error registering a proving key on Coordinator contract" + ErrRegisterProvingKey = "error registering proving keys" + ErrEncodingProvingKey = "error encoding proving key" + ErrDeployBlockHashStore = "error deploying blockhash store" + ErrDeployBatchBlockHashStore = "error deploying batch blockhash store" + ErrDeployCoordinator = "error deploying VRF CoordinatorV2" + ErrABIEncodingFunding = "error Abi encoding subscriptionID" + ErrSendingLinkToken = "error sending Link token" + ErrCreatingBHSJob = "error creating BHS job" + ErrParseJob = "error parsing job definition" + ErrSetVRFCoordinatorConfig = "error setting config for VRF Coordinator contract" + ErrCreateVRFSubscription = "error creating VRF Subscription" + ErrAddConsumerToSub = "error adding consumer to VRF Subscription" + ErrFundSubWithLinkToken = "error funding subscription with Link tokens" + ErrRestartCLNode = "error restarting CL node" + ErrWaitTXsComplete = "error waiting for TXs to complete" + ErrRequestRandomness = "error requesting randomness" + ErrLoadingCoordinator = "error loading coordinator contract" + ErrCreatingVRFKey = "error creating VRF key" ErrWaitRandomWordsRequestedEvent = "error waiting for RandomWordsRequested event" ErrWaitRandomWordsFulfilledEvent = "error waiting for RandomWordsFulfilled event" diff --git a/integration-tests/actions/vrf/common/models.go b/integration-tests/actions/vrf/common/models.go index 479b7680330..d5c1c2b95b0 100644 --- a/integration-tests/actions/vrf/common/models.go +++ b/integration-tests/actions/vrf/common/models.go @@ -25,10 +25,11 @@ type VRFNodeType int const ( VRF VRFNodeType = iota + 1 BHS + BHF ) func (n VRFNodeType) String() string { - return [...]string{"VRF", "BHS"}[n-1] + return [...]string{"VRF", "BHS", "BHF"}[n-1] } func (n VRFNodeType) Index() int { @@ -46,6 +47,7 @@ type VRFContracts struct { CoordinatorV2Plus contracts.VRFCoordinatorV2_5 VRFOwner contracts.VRFOwner BHS contracts.BlockHashStore + BatchBHS contracts.BatchBlockhashStore VRFV2Consumers []contracts.VRFv2LoadTestConsumer VRFV2PlusConsumer []contracts.VRFv2PlusLoadTestConsumer LinkToken contracts.LinkToken diff --git a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go index 308cdd5f8fa..5df33a6d997 100644 --- a/integration-tests/actions/vrf/vrfv2plus/contract_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/contract_steps.go @@ -35,6 +35,14 @@ func DeployVRFV2_5Contracts( if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrWaitTXsComplete, err) } + batchBHS, err := contractDeployer.DeployBatchBlockhashStore(bhs.Address()) + if err != nil { + return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployBatchBlockHashStore, err) + } + err = chainClient.WaitForEvents() + if err != nil { + return nil, fmt.Errorf("%s, batchBHS err %w", vrfcommon.ErrWaitTXsComplete, err) + } coordinator, err := contractDeployer.DeployVRFCoordinatorV2_5(bhs.Address()) if err != nil { return nil, fmt.Errorf("%s, err %w", vrfcommon.ErrDeployCoordinator, err) @@ -46,6 +54,7 @@ func DeployVRFV2_5Contracts( return &vrfcommon.VRFContracts{ CoordinatorV2Plus: coordinator, BHS: bhs, + BatchBHS: batchBHS, VRFV2PlusConsumer: nil, }, nil } diff --git a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go index 2fb73cb1f77..3d698ffec32 100644 --- a/integration-tests/actions/vrf/vrfv2plus/setup_steps.go +++ b/integration-tests/actions/vrf/vrfv2plus/setup_steps.go @@ -160,6 +160,27 @@ func SetupVRFV2_5Environment( }) } + if bhfNode, exists := nodeTypeToNodeMap[vrfcommon.BHF]; exists { + g.Go(func() error { + err := vrfcommon.SetupBHFNode( + env, + configGeneral.General, + numberOfTxKeysToCreate, + big.NewInt(chainID), + vrfContracts.CoordinatorV2Plus.Address(), + vrfContracts.BHS.Address(), + vrfContracts.BatchBHS.Address(), + *vrfv2PlusTestConfig.GetCommonConfig().ChainlinkNodeFunding, + l, + bhfNode, + ) + if err != nil { + return err + } + return nil + }) + } + if err := g.Wait(); err != nil { return nil, nil, nil, fmt.Errorf("VRF node setup ended up with an error: %w", err) } diff --git a/integration-tests/benchmark/keeper_test.go b/integration-tests/benchmark/keeper_test.go index e6cda6d7f27..8aa733ea101 100644 --- a/integration-tests/benchmark/keeper_test.go +++ b/integration-tests/benchmark/keeper_test.go @@ -165,6 +165,7 @@ func TestAutomationBenchmark(t *testing.T) { FallbackLinkPrice: big.NewInt(2e18), MaxCheckDataSize: uint32(5_000), MaxPerformDataSize: uint32(5_000), + MaxRevertDataSize: uint32(5_000), }, Upkeeps: &testsetups.UpkeepConfig{ NumberOfUpkeeps: *config.Keeper.Common.NumberOfUpkeeps, diff --git a/integration-tests/chaos/automation_chaos_test.go b/integration-tests/chaos/automation_chaos_test.go index fac9f83ba79..56b0d1e32b6 100644 --- a/integration-tests/chaos/automation_chaos_test.go +++ b/integration-tests/chaos/automation_chaos_test.go @@ -92,6 +92,7 @@ ListenAddresses = ["0.0.0.0:6690"]` FallbackLinkPrice: big.NewInt(2e18), MaxCheckDataSize: uint32(5000), MaxPerformDataSize: uint32(5000), + MaxRevertDataSize: uint32(5000), } ) diff --git a/integration-tests/client/chainlink_models.go b/integration-tests/client/chainlink_models.go index b380d9a28dd..d19888fb706 100644 --- a/integration-tests/client/chainlink_models.go +++ b/integration-tests/client/chainlink_models.go @@ -1328,6 +1328,48 @@ runTimeout = "{{.RunTimeout}}" return MarshallTemplate(b, "BlockhashStore Job", vrfTemplateString) } +// BlockHeaderFeederJobSpec represents a blockheaderfeeder job +type BlockHeaderFeederJobSpec struct { + Name string `toml:"name"` + CoordinatorV2Address string `toml:"coordinatorV2Address"` + CoordinatorV2PlusAddress string `toml:"coordinatorV2PlusAddress"` + BlockhashStoreAddress string `toml:"blockhashStoreAddress"` + BatchBlockhashStoreAddress string `toml:"batchBlockhashStoreAddress"` + ExternalJobID string `toml:"externalJobID"` + FromAddresses []string `toml:"fromAddresses"` + EVMChainID string `toml:"evmChainID"` + ForwardingAllowed bool `toml:"forwardingAllowed"` + PollPeriod time.Duration `toml:"pollPeriod"` + RunTimeout time.Duration `toml:"runTimeout"` + WaitBlocks int `toml:"waitBlocks"` + LookbackBlocks int `toml:"lookbackBlocks"` +} + +// Type returns the type of the job +func (b *BlockHeaderFeederJobSpec) Type() string { return "blockheaderfeeder" } + +// String representation of the job +func (b *BlockHeaderFeederJobSpec) String() (string, error) { + vrfTemplateString := ` +type = "blockheaderfeeder" +schemaVersion = 1 +name = "{{.Name}}" +forwardingAllowed = {{.ForwardingAllowed}} +coordinatorV2Address = "{{.CoordinatorV2Address}}" +coordinatorV2PlusAddress = "{{.CoordinatorV2PlusAddress}}" +blockhashStoreAddress = "{{.BlockhashStoreAddress}}" +batchBlockhashStoreAddress = "{{.BatchBlockhashStoreAddress}}" +fromAddresses = [{{range .FromAddresses}}"{{.}}",{{end}}] +evmChainID = "{{.EVMChainID}}" +externalJobID = "{{.ExternalJobID}}" +waitBlocks = {{.WaitBlocks}} +lookbackBlocks = {{.LookbackBlocks}} +pollPeriod = "{{.PollPeriod}}" +runTimeout = "{{.RunTimeout}}" +` + return MarshallTemplate(b, "BlockHeaderFeeder Job", vrfTemplateString) +} + // WebhookJobSpec reprsents a webhook job type WebhookJobSpec struct { Name string `toml:"name"` diff --git a/integration-tests/contracts/contract_deployer.go b/integration-tests/contracts/contract_deployer.go index 11dae558f7d..c8b1d18d0bd 100644 --- a/integration-tests/contracts/contract_deployer.go +++ b/integration-tests/contracts/contract_deployer.go @@ -111,7 +111,7 @@ type ContractDeployer interface { LoadKeeperRegistry(address common.Address, registryVersion eth_contracts.KeeperRegistryVersion) (KeeperRegistry, error) DeployKeeperConsumer(updateInterval *big.Int) (KeeperConsumer, error) DeployAutomationLogTriggerConsumer(testInterval *big.Int) (KeeperConsumer, error) - DeployAutomationSimpleLogTriggerConsumer() (KeeperConsumer, error) + DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) DeployAutomationStreamsLookupUpkeepConsumer(testRange *big.Int, interval *big.Int, useArbBlock bool, staging bool, verify bool) (KeeperConsumer, error) DeployAutomationLogTriggeredStreamsLookupUpkeepConsumer() (KeeperConsumer, error) DeployKeeperConsumerPerformance( @@ -1517,13 +1517,13 @@ func (e *EthereumContractDeployer) DeployAutomationLogTriggerConsumer(testInterv }, err } -func (e *EthereumContractDeployer) DeployAutomationSimpleLogTriggerConsumer() (KeeperConsumer, error) { +func (e *EthereumContractDeployer) DeployAutomationSimpleLogTriggerConsumer(isStreamsLookup bool) (KeeperConsumer, error) { address, _, instance, err := e.client.DeployContract("SimpleLogUpkeepCounter", func( auth *bind.TransactOpts, backend bind.ContractBackend, ) (common.Address, *types.Transaction, interface{}, error) { return simple_log_upkeep_counter_wrapper.DeploySimpleLogUpkeepCounter( - auth, backend, + auth, backend, isStreamsLookup, ) }) if err != nil { diff --git a/integration-tests/contracts/ethereum_keeper_contracts.go b/integration-tests/contracts/ethereum_keeper_contracts.go index 0a516d5029b..337e3009f16 100644 --- a/integration-tests/contracts/ethereum_keeper_contracts.go +++ b/integration-tests/contracts/ethereum_keeper_contracts.go @@ -174,6 +174,7 @@ type KeeperRegistrySettings struct { FallbackLinkPrice *big.Int // LINK price used if the LINK price feed is stale MaxCheckDataSize uint32 MaxPerformDataSize uint32 + MaxRevertDataSize uint32 RegistryVersion ethereum.KeeperRegistryVersion } @@ -258,7 +259,7 @@ func (rcs *KeeperRegistrySettings) Create22OnchainConfig(registrar string, regis MaxPerformGas: rcs.MaxPerformGas, MaxCheckDataSize: rcs.MaxCheckDataSize, MaxPerformDataSize: rcs.MaxPerformDataSize, - MaxRevertDataSize: uint32(1000), + MaxRevertDataSize: rcs.MaxRevertDataSize, FallbackGasPrice: rcs.FallbackGasPrice, FallbackLinkPrice: rcs.FallbackLinkPrice, Transcoder: common.Address{}, @@ -280,7 +281,7 @@ func (rcs *KeeperRegistrySettings) Create21OnchainConfig(registrar string, regis MaxPerformGas: rcs.MaxPerformGas, MaxCheckDataSize: rcs.MaxCheckDataSize, MaxPerformDataSize: rcs.MaxPerformDataSize, - MaxRevertDataSize: uint32(1000), + MaxRevertDataSize: rcs.MaxRevertDataSize, FallbackGasPrice: rcs.FallbackGasPrice, FallbackLinkPrice: rcs.FallbackLinkPrice, Transcoder: common.Address{}, diff --git a/integration-tests/docker/test_env/test_env_builder.go b/integration-tests/docker/test_env/test_env_builder.go index 07d14f1885c..14a4c1df6fa 100644 --- a/integration-tests/docker/test_env/test_env_builder.go +++ b/integration-tests/docker/test_env/test_env_builder.go @@ -298,7 +298,7 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return nil, err } - //TODO remove after fixing in CTF + // TODO: remove after fixing in CTF networkConfig.ChainID = int64(en.EthereumChainConfig.ChainID) if b.hasEVMClient { @@ -338,27 +338,41 @@ func (b *CLTestEnvBuilder) Build() (*CLClusterTestEnv, error) { return b.te, nil } + b.te.rpcProviders = make(map[int64]*test_env.RpcProvider) networkConfig := networks.MustGetSelectedNetworkConfig(b.testConfig.GetNetworkConfig())[0] + // This has some hidden behavior so I'm not the biggest fan, but it matches expected behavior. + // That is, when we specify we want to run on a live network in our config, we will run on the live network and not bother with a private network. + // Even if we explicitly declare that we want to run on a private network in the test. + // Keeping this a Kludge for now as SETH transition should change all of this anyway. if len(b.privateEthereumNetworks) == 1 { - b.te.rpcProviders = make(map[int64]*test_env.RpcProvider) - // TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point - // in general it seems we have no methods for saving config to file and we only load it from file - // but I don't know how that config file is to be created or whether anyone ever done that - var rpcProvider test_env.RpcProvider - - b.privateEthereumNetworks[0].DockerNetworkNames = []string{b.te.DockerNetwork.Name} - networkConfig, rpcProvider, err = b.te.StartEthereumNetwork(b.privateEthereumNetworks[0]) - if err != nil { - return nil, err + if networkConfig.Simulated { + // TODO here we should save the ethereum network config to te.Cfg, but it doesn't exist at this point + // in general it seems we have no methods for saving config to file and we only load it from file + // but I don't know how that config file is to be created or whether anyone ever done that + var rpcProvider test_env.RpcProvider + b.privateEthereumNetworks[0].DockerNetworkNames = []string{b.te.DockerNetwork.Name} + networkConfig, rpcProvider, err = b.te.StartEthereumNetwork(b.privateEthereumNetworks[0]) + if err != nil { + return nil, err + } + b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider + b.te.PrivateEthereumConfigs = b.privateEthereumNetworks + + b.te.isSimulatedNetwork = true + } else { // Only start and connect to a private network if we are using a private simulated network + b.te.l.Warn(). + Str("Network", networkConfig.Name). + Int64("Chain ID", networkConfig.ChainID). + Msg("Private network config provided, but we are running on a live network. Ignoring private network config.") + rpcProvider := test_env.NewRPCProvider(networkConfig.HTTPURLs, networkConfig.URLs, networkConfig.HTTPURLs, networkConfig.URLs) + b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider + b.te.isSimulatedNetwork = false } - b.te.rpcProviders[networkConfig.ChainID] = &rpcProvider - b.te.PrivateEthereumConfigs = b.privateEthereumNetworks - b.te.isSimulatedNetwork = true } if !b.hasSeth && !b.hasEVMClient { - return nil, errors.New("you need to specify, which evm client to use: Seth or EMVClient") + return nil, errors.New("you need to specify, which evm client to use: Seth or EVMClient") } if b.hasSeth && b.hasEVMClient { diff --git a/integration-tests/go.mod b/integration-tests/go.mod index f7a37e3fbb7..27c096335a1 100644 --- a/integration-tests/go.mod +++ b/integration-tests/go.mod @@ -24,10 +24,10 @@ require ( github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240324144450-2bc22a6738ac - github.com/smartcontractkit/chainlink-testing-framework v1.27.3 + github.com/smartcontractkit/chainlink-testing-framework v1.27.8 github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 github.com/smartcontractkit/chainlink/v2 v2.0.0-00010101000000-000000000000 - github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 + github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/smartcontractkit/seth v0.1.2 github.com/smartcontractkit/wasp v0.4.5 github.com/spf13/cobra v1.8.0 @@ -81,6 +81,8 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/NethermindEth/juno v0.3.1 // indirect + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect @@ -92,6 +94,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816 // indirect @@ -274,6 +277,7 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect @@ -374,13 +378,12 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // 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-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 - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect + 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 @@ -413,6 +416,7 @@ require ( github.com/ugorji/go/codec v1.2.12 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.1.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -483,7 +487,7 @@ require ( sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( diff --git a/integration-tests/go.sum b/integration-tests/go.sum index 928b6b7a78c..fe3706fe106 100644 --- a/integration-tests/go.sum +++ b/integration-tests/go.sum @@ -148,6 +148,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -215,6 +219,8 @@ github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYS github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= 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/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= @@ -1002,6 +1008,8 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -1470,6 +1478,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1511,8 +1521,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= @@ -1527,18 +1535,18 @@ github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e h1:k8HS3GsAFZnxXIW3141VsQP2+EL1XrTtOi/HDt7sdBE= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e/go.mod h1:JiykN+8W5TA4UD2ClrzQCVvcH3NcyLEVv7RwY0busrw= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3 h1:rUvTtLXPcxI5s3AttdpWeWTNXAprrjyyBvBEvYZp994= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8 h1:V1G4hVjztvFuY6dPfBdv53OzQ99lwLUraXH0Wapyh3Q= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868/go.mod h1:Kn1Hape05UzFZ7bOUnm3GVsHzP0TNrVmpfXYNHdqGGs= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16 h1:TFe+FvzxClblt6qRfqEhUfa4kFQx5UobuoFGO2W4mMo= github.com/smartcontractkit/go-plugin v0.0.0-20240208201424-b3b91517de16/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +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.2 h1:ImXJmniuq6yWB6b3eezjV+lkYb1GfQuaJkwRvrCfTKQ= github.com/smartcontractkit/seth v0.1.2/go.mod h1:aOaGwrIVFG/MYaLSj9UUMyE5QJnYQoAgnxm5cKfT9Ng= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= @@ -1682,6 +1690,8 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -2435,5 +2445,5 @@ sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2 sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/integration-tests/load/automationv2_1/automationv2_1_test.go b/integration-tests/load/automationv2_1/automationv2_1_test.go index d199ddd7b85..ccac4c0af12 100644 --- a/integration-tests/load/automationv2_1/automationv2_1_test.go +++ b/integration-tests/load/automationv2_1/automationv2_1_test.go @@ -2,14 +2,21 @@ package automationv2_1 import ( "context" + "encoding/hex" "fmt" + "io" "math" "math/big" + "net/http" "strconv" "strings" "testing" "time" + "github.com/pkg/errors" + + "github.com/smartcontractkit/chainlink-testing-framework/k8s/pkg/helm/wiremock" + geth "github.com/ethereum/go-ethereum" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" @@ -32,6 +39,8 @@ import ( ctfconfig "github.com/smartcontractkit/chainlink-testing-framework/config" + gowiremock "github.com/wiremock/go-wiremock" + "github.com/smartcontractkit/chainlink/integration-tests/actions" "github.com/smartcontractkit/chainlink/integration-tests/actions/automationv2" "github.com/smartcontractkit/chainlink/integration-tests/client" @@ -62,6 +71,11 @@ Enabled = true Enabled = true AnnounceAddresses = ["0.0.0.0:6690"] ListenAddresses = ["0.0.0.0:6690"]` + secretsTOML = `[Mercury.Credentials.%s] +LegacyURL = '%s' +URL = '%s' +Username = '%s' +Password = '%s'` minimumNodeSpec = map[string]interface{}{ "resources": map[string]interface{}{ @@ -118,6 +132,35 @@ ListenAddresses = ["0.0.0.0:6690"]` } ) +func setUpDataStreamsWireMock(url string) error { + wm := gowiremock.NewClient(url) + rule200 := gowiremock.Get(gowiremock.URLPathEqualTo("/api/v1/reports/bulk")). + WithQueryParam("feedIDs", gowiremock.EqualTo("0x000200")). + WillReturnResponse(gowiremock.NewResponse(). + WithBody(`{"reports":[{"feedID":"0x000200","validFromTimestamp":0,"observationsTimestamp":0,"fullReport":"0x000abc"}]}`). + WithStatus(200)) + err := wm.StubFor(rule200) + if err != nil { + return err + } + resp, err := http.Post(fmt.Sprintf("%s/__admin/mappings/save", url), "application/json", nil) + if err != nil { + return errors.New("error saving wiremock mappings") + } + defer func(Body io.ReadCloser) { + err := Body.Close() + if err != nil { + panic(err) + } + }(resp.Body) + + if resp.StatusCode != 200 { + return errors.New("error saving wiremock mappings") + } + + return nil +} + func TestLogTrigger(t *testing.T) { ctx := tests.Context(t) l := logging.GetTestLogger(t) @@ -177,6 +220,7 @@ Load Config: FallbackLinkPrice: big.NewInt(2e18), MaxCheckDataSize: uint32(5_000), MaxPerformDataSize: uint32(5_000), + MaxRevertDataSize: uint32(5_000), RegistryVersion: contractseth.RegistryVersion_2_1, } @@ -235,6 +279,33 @@ Load Config: loadedTestConfig.Pyroscope.Environment = &testEnvironment.Cfg.Namespace } + if *loadedTestConfig.Automation.DataStreams.Enabled { + if loadedTestConfig.Automation.DataStreams.URL == nil || *loadedTestConfig.Automation.DataStreams.URL == "" { + testEnvironment.AddHelm(wiremock.New(nil)) + err := testEnvironment.Run() + require.NoError(t, err, "Error running wiremock server") + wiremockURL := testEnvironment.URLs[wiremock.InternalURLsKey][0] + secretsTOML = fmt.Sprintf( + secretsTOML, "cred1", + wiremockURL, wiremockURL, + "username", "password", + ) + if !testEnvironment.Cfg.InsideK8s { + wiremockURL = testEnvironment.URLs[wiremock.LocalURLsKey][0] + } + err = setUpDataStreamsWireMock(wiremockURL) + require.NoError(t, err, "Error setting up wiremock server") + } else { + secretsTOML = fmt.Sprintf( + secretsTOML, "cred1", + *loadedTestConfig.Automation.DataStreams.URL, *loadedTestConfig.Automation.DataStreams.URL, + *loadedTestConfig.Automation.DataStreams.Username, *loadedTestConfig.Automation.DataStreams.Password, + ) + } + } else { + secretsTOML = "" + } + numberOfUpkeeps := *loadedTestConfig.Automation.General.NumberOfNodes for i := 0; i < numberOfUpkeeps+1; i++ { // +1 for the OCR boot node @@ -252,10 +323,11 @@ Load Config: } cd := chainlink.NewWithOverride(i, map[string]any{ - "toml": nodeTOML, - "chainlink": nodeSpec, - "db": dbSpec, - "prometheus": *loadedTestConfig.Automation.General.UsePrometheus, + "toml": nodeTOML, + "chainlink": nodeSpec, + "db": dbSpec, + "prometheus": *loadedTestConfig.Automation.General.UsePrometheus, + "secretsToml": secretsTOML, }, loadedTestConfig.ChainlinkImage, overrideFn) testEnvironment.AddHelm(cd) @@ -310,6 +382,10 @@ Load Config: F: 1, } + if *loadedTestConfig.Automation.DataStreams.Enabled { + a.MercuryCredentialName = "cred1" + } + startTimeTestSetup := time.Now() l.Info().Str("START_TIME", startTimeTestSetup.String()).Msg("Test setup started") @@ -344,7 +420,7 @@ Load Config: for _, u := range loadedTestConfig.Automation.Load { for i := 0; i < *u.NumberOfUpkeeps; i++ { - consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer() + consumerContract, err := contractDeployer.DeployAutomationSimpleLogTriggerConsumer(*u.IsStreamsLookup) require.NoError(t, err, "Error deploying automation consumer contract") consumerContracts = append(consumerContracts, consumerContract) l.Debug(). @@ -361,6 +437,11 @@ Load Config: PerformBurnAmount: u.PerformBurnAmount, UpkeepGasLimit: u.UpkeepGasLimit, SharedTrigger: u.SharedTrigger, + Feeds: []string{}, + } + + if *u.IsStreamsLookup { + loadCfg.Feeds = u.Feeds } loadConfigs = append(loadConfigs, loadCfg) @@ -394,17 +475,22 @@ Load Config: } encodedLogTriggerConfig, err := convenienceABI.Methods["_logTriggerConfig"].Inputs.Pack(&logTriggerConfigStruct) require.NoError(t, err, "Error encoding log trigger config") - l.Debug().Bytes("Encoded Log Trigger Config", encodedLogTriggerConfig).Msg("Encoded Log Trigger Config") + l.Debug(). + Interface("logTriggerConfigStruct", logTriggerConfigStruct). + Str("Encoded Log Trigger Config", hex.EncodeToString(encodedLogTriggerConfig)).Msg("Encoded Log Trigger Config") checkDataStruct := simple_log_upkeep_counter_wrapper.CheckData{ CheckBurnAmount: loadConfigs[i].CheckBurnAmount, PerformBurnAmount: loadConfigs[i].PerformBurnAmount, EventSig: bytes1, + Feeds: loadConfigs[i].Feeds, } encodedCheckDataStruct, err := consumerABI.Methods["_checkDataConfig"].Inputs.Pack(&checkDataStruct) require.NoError(t, err, "Error encoding check data struct") - l.Debug().Bytes("Encoded Check Data Struct", encodedCheckDataStruct).Msg("Encoded Check Data Struct") + l.Debug(). + Interface("checkDataStruct", checkDataStruct). + Str("Encoded Check Data Struct", hex.EncodeToString(encodedCheckDataStruct)).Msg("Encoded Check Data Struct") upkeepConfig := automationv2.UpkeepConfig{ UpkeepName: fmt.Sprintf("LogTriggerUpkeep-%d", i), diff --git a/integration-tests/load/go.mod b/integration-tests/load/go.mod index 0adeb80967c..94fe55b770f 100644 --- a/integration-tests/load/go.mod +++ b/integration-tests/load/go.mod @@ -12,18 +12,20 @@ require ( github.com/ethereum/go-ethereum v1.13.8 github.com/go-resty/resty/v2 v2.11.0 github.com/pelletier/go-toml/v2 v2.1.1 + github.com/pkg/errors v0.9.1 github.com/rs/zerolog v1.30.0 github.com/slack-go/slack v0.12.2 github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 github.com/smartcontractkit/chainlink-common v0.1.7-0.20240324144450-2bc22a6738ac - github.com/smartcontractkit/chainlink-testing-framework v1.27.3 + github.com/smartcontractkit/chainlink-testing-framework v1.27.8 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-20240229181116-bfb2432a7a66 + github.com/smartcontractkit/libocr v0.0.0-20240326191951-2bbe9382d052 github.com/smartcontractkit/seth v0.1.2 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 + github.com/wiremock/go-wiremock v1.9.0 go.uber.org/ratelimit v0.3.0 ) @@ -58,6 +60,8 @@ require ( github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect + github.com/NethermindEth/juno v0.3.1 // indirect + github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 // indirect github.com/VictoriaMetrics/fastcache v1.12.1 // indirect github.com/XSAM/otelsql v0.27.0 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect @@ -69,6 +73,7 @@ require ( github.com/aws/constructs-go/constructs/v10 v10.1.255 // indirect github.com/aws/jsii-runtime-go v1.75.0 // indirect github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 // indirect + github.com/bahlo/generic-list-go v0.2.0 // indirect github.com/barkimedes/go-deepcopy v0.0.0-20220514131651-17c30cfc62df // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect @@ -256,6 +261,7 @@ require ( github.com/huin/goupnp v1.3.0 // indirect github.com/imdario/mergo v0.3.16 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/invopop/jsonschema v0.12.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect github.com/jackc/pgio v1.0.0 // indirect @@ -336,7 +342,6 @@ require ( github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/alertmanager v0.26.0 // indirect @@ -362,13 +367,12 @@ require ( github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/shopspring/decimal v1.3.1 // indirect github.com/sirupsen/logrus v1.9.3 // indirect - github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 // 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-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 - github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 // indirect + github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 // indirect github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea // indirect github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 // indirect github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 // indirect @@ -406,6 +410,7 @@ require ( github.com/umbracle/ethgo v0.1.3 // indirect github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 // indirect github.com/valyala/fastjson v1.4.1 // indirect + github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect github.com/x448/float16 v0.8.4 // indirect github.com/xlab/treeprint v1.1.0 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -480,7 +485,7 @@ require ( sigs.k8s.io/kustomize/api v0.12.1 // indirect sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) replace ( diff --git a/integration-tests/load/go.sum b/integration-tests/load/go.sum index e721dde4cdd..4eaea1088d6 100644 --- a/integration-tests/load/go.sum +++ b/integration-tests/load/go.sum @@ -148,6 +148,10 @@ github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migc github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= +github.com/NethermindEth/juno v0.3.1 h1:AW72LiAm9gqUeCVJWvepnZcTnpU4Vkl0KzPMxS+42FA= +github.com/NethermindEth/juno v0.3.1/go.mod h1:SGbTpgGaCsxhFsKOid7Ylnz//WZ8swtILk+NbHGsk/Q= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1 h1:9SBvy3eZut1X+wEyAFqfb7ADGj8IQw7ZnlkMwz0YOTY= +github.com/NethermindEth/starknet.go v0.6.1-0.20231218140327-915109ab5bc1/go.mod h1:V6qrbi1+fTDCftETIT1grBXIf+TvWP/4Aois1a9EF1E= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= @@ -215,6 +219,8 @@ github.com/aws/jsii-runtime-go v1.75.0/go.mod h1:TKCyrtM0pygEPo4rDZzbMSDNCDNTSYS github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59 h1:WWB576BN5zNSZc/M9d/10pqEx5VHNhaQ/yOVAkmj5Yo= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= 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/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= @@ -991,6 +997,8 @@ github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPt github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/invopop/jsonschema v0.12.0 h1:6ovsNSuvn9wEQVOyc72aycBMVQFKz7cPdMJn10CvzRI= +github.com/invopop/jsonschema v0.12.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0= github.com/ionos-cloud/sdk-go/v6 v6.1.8 h1:493wE/BkZxJf7x79UCE0cYGPZoqQcPiEBALvt7uVGY0= github.com/ionos-cloud/sdk-go/v6 v6.1.8/go.mod h1:EzEgRIDxBELvfoa/uBN0kOQaqovLjUWEB7iW4/Q+t4k= github.com/iris-contrib/blackfriday v2.0.0+incompatible/go.mod h1:UzZ2bDEoaSGPbkg6SAB4att1aAwTmVIx/5gCVqeyUdI= @@ -1453,6 +1461,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 h1:lZUw3E0/J3roVtGQ+SCrUrg3ON6NgVqpn3+iol9aGu4= +github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPOhJotwFIyu2bBVN41fcDUY= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= @@ -1494,8 +1504,6 @@ github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/slack-go/slack v0.12.2 h1:x3OppyMyGIbbiyFhsBmpf9pwkUzMhthJMRNmNlA4LaQ= github.com/slack-go/slack v0.12.2/go.mod h1:hlGi5oXA+Gt+yWTPP0plCdRKmjsDxecdHxYQdlMQKOw= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704 h1:T3lFWumvbfM1u/etVq42Afwq/jtNSBSOA8n5jntnNPo= -github.com/smartcontractkit/caigo v0.0.0-20230621050857-b29a4ca8c704/go.mod h1:2QuJdEouTWjh5BDy5o/vgGXQtR4Gz8yH1IYB5eT7u4M= github.com/smartcontractkit/chain-selectors v1.0.10 h1:t9kJeE6B6G+hKD0GYR4kGJSCqR1LNS7aI3jT0V+xGrg= github.com/smartcontractkit/chain-selectors v1.0.10/go.mod h1:d4Hi+E1zqjy9HqMkjBE5q1vcG9VGgxf5VxiRHfzi2kE= github.com/smartcontractkit/chainlink-automation v1.0.2-0.20240311111125-22812a072c35 h1:GNhRKD3izyzAoGMXDvVUAwEuzz4Atdj3U3RH7eak5Is= @@ -1510,10 +1518,10 @@ github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8 h github.com/smartcontractkit/chainlink-feeds v0.0.0-20240119021347-3c541a78cdb8/go.mod h1:vy1L7NybTy2F/Yv7BOh+oZBa1MACD6gzd1+DkcSkfp8= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e h1:k8HS3GsAFZnxXIW3141VsQP2+EL1XrTtOi/HDt7sdBE= github.com/smartcontractkit/chainlink-solana v1.0.3-0.20240216142700-c5869534c19e/go.mod h1:JiykN+8W5TA4UD2ClrzQCVvcH3NcyLEVv7RwY0busrw= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0 h1:7m9PVtccb8/pvKTXMaGuyceFno1icRyC2SFH7KG7+70= -github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240213121419-1272736c2ac0/go.mod h1:SZ899lZYQ0maUulWbZg+SWqabHQ1wTbyk3jT8wJfyo8= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3 h1:rUvTtLXPcxI5s3AttdpWeWTNXAprrjyyBvBEvYZp994= -github.com/smartcontractkit/chainlink-testing-framework v1.27.3/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595 h1:y6ks0HsSOhPUueOmTcoxDQ50RCS1XINlRDTemZyHjFw= +github.com/smartcontractkit/chainlink-starknet/relayer v0.0.1-beta-test.0.20240325075535-0f7eb05ee595/go.mod h1:vV6WfnVIbK5Q1JsIru4YcTG0T1uRpLJm6t2BgCnCSsg= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8 h1:V1G4hVjztvFuY6dPfBdv53OzQ99lwLUraXH0Wapyh3Q= +github.com/smartcontractkit/chainlink-testing-framework v1.27.8/go.mod h1:jN+HgXbriq6fKRlIqLw9F3I81aYImV6kBJkIfz0mdIA= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea h1:ZdLmNAfKRjH8AYUvjiiDGUgiWQfq/7iNpxyTkvjx/ko= github.com/smartcontractkit/chainlink-testing-framework/grafana v0.0.0-20240227164431-18a7065e23ea/go.mod h1:gCKC9w6XpNk6jm+XIk2psrkkfxhi421N9NSiFceXW88= github.com/smartcontractkit/chainlink-vrf v0.0.0-20231120191722-fef03814f868 h1:FFdvEzlYwcuVHkdZ8YnZR/XomeMGbz5E2F2HZI3I3w8= @@ -1522,8 +1530,8 @@ github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306 h1:ko88 github.com/smartcontractkit/go-plugin v0.0.0-20231003134350-e49dad63b306/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f h1:hgJif132UCdjo8u43i7iPN1/MFnu49hv7lFGFftCHKU= github.com/smartcontractkit/grpc-proxy v0.0.0-20230731113816-f1be6620749f/go.mod h1:MvMXoufZAtqExNexqi4cjrNYE9MefKddKylxjS+//n0= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66 h1:xsU00JB9GJxEiN6tDbqgN+fT98ySdxkUwTw6CfBXscw= -github.com/smartcontractkit/libocr v0.0.0-20240229181116-bfb2432a7a66/go.mod h1:SJEZCHgMCAzzBvo9vMV2DQ9onfEcIJCYSViyP4JI6c4= +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.2 h1:ImXJmniuq6yWB6b3eezjV+lkYb1GfQuaJkwRvrCfTKQ= github.com/smartcontractkit/seth v0.1.2/go.mod h1:aOaGwrIVFG/MYaLSj9UUMyE5QJnYQoAgnxm5cKfT9Ng= github.com/smartcontractkit/tdh2/go/ocr2/decryptionplugin v0.0.0-20230906073235-9e478e5e19f1 h1:yiKnypAqP8l0OX0P3klzZ7SCcBUxy5KqTAKZmQOvSQE= @@ -1665,6 +1673,10 @@ github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+ github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= github.com/vultr/govultr/v2 v2.17.2 h1:gej/rwr91Puc/tgh+j33p/BLR16UrIPnSr+AIwYWZQs= github.com/vultr/govultr/v2 v2.17.2/go.mod h1:ZFOKGWmgjytfyjeyAdhQlSWwTjh2ig+X49cAp50dzXI= +github.com/wiremock/go-wiremock v1.9.0 h1:9xcU4/IoEfgCaH4TGhQTtiQyBh2eMtu9JB6ppWduK+E= +github.com/wiremock/go-wiremock v1.9.0/go.mod h1:/uvO0XFheyy8XetvQqm4TbNQRsGPlByeNegzLzvXs0c= +github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc= +github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= @@ -2420,5 +2432,5 @@ sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2 sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4= sigs.k8s.io/structured-merge-diff/v4 v4.3.0 h1:UZbZAZfX0wV2zr7YZorDz6GXROfDFj6LvqCRm4VUVKk= sigs.k8s.io/structured-merge-diff/v4 v4.3.0/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/integration-tests/reorg/automation_reorg_test.go b/integration-tests/reorg/automation_reorg_test.go index fe87ac1aa3f..7a2215c36f0 100644 --- a/integration-tests/reorg/automation_reorg_test.go +++ b/integration-tests/reorg/automation_reorg_test.go @@ -96,6 +96,7 @@ LimitDefault = 5_000_000` FallbackLinkPrice: big.NewInt(2e18), MaxCheckDataSize: uint32(5000), MaxPerformDataSize: uint32(5000), + MaxRevertDataSize: uint32(5000), } ) diff --git a/integration-tests/smoke/automation_test.go b/integration-tests/smoke/automation_test.go index 2ee01fa21c9..d69173b47d3 100644 --- a/integration-tests/smoke/automation_test.go +++ b/integration-tests/smoke/automation_test.go @@ -58,6 +58,7 @@ var ( FallbackLinkPrice: big.NewInt(2e18), MaxCheckDataSize: uint32(5000), MaxPerformDataSize: uint32(5000), + MaxRevertDataSize: uint32(5000), } ) diff --git a/integration-tests/smoke/vrfv2plus_test.go b/integration-tests/smoke/vrfv2plus_test.go index 8c7cfd3a4d2..18e90dcc9a9 100644 --- a/integration-tests/smoke/vrfv2plus_test.go +++ b/integration-tests/smoke/vrfv2plus_test.go @@ -1424,6 +1424,161 @@ func TestVRFV2PlusWithBHS(t *testing.T) { }) } +func TestVRFV2PlusWithBHF(t *testing.T) { + t.Parallel() + var ( + env *test_env.CLClusterTestEnv + vrfContracts *vrfcommon.VRFContracts + subIDsForCancellingAfterTest []*big.Int + defaultWalletAddress string + vrfKey *vrfcommon.VRFKeyData + nodeTypeToNodeMap map[vrfcommon.VRFNodeType]*vrfcommon.VRFNode + ) + l := logging.GetTestLogger(t) + + config, err := tc.GetConfig("Smoke", tc.VRFv2Plus) + require.NoError(t, err, "Error getting config") + vrfv2PlusConfig := config.VRFv2Plus + + chainID := networks.MustGetSelectedNetworkConfig(config.GetNetworkConfig())[0].ChainID + + cleanupFn := func() { + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + if evmClient.NetworkSimulated() { + l.Info(). + Str("Network Name", evmClient.GetNetworkName()). + Msg("Network is a simulated network. Skipping fund return for Coordinator Subscriptions.") + } else { + if *vrfv2PlusConfig.General.CancelSubsAfterTestRun { + //cancel subs and return funds to sub owner + vrfv2plus.CancelSubsAndReturnFunds(testcontext.Get(t), vrfContracts, defaultWalletAddress, subIDsForCancellingAfterTest, l) + } + } + if !*vrfv2PlusConfig.General.UseExistingEnv { + if err := env.Cleanup(); err != nil { + l.Error().Err(err).Msg("Error cleaning up test environment") + } + } + } + + // BHF job config + config.VRFv2Plus.General.BHFJobWaitBlocks = ptr.Ptr(260) + config.VRFv2Plus.General.BHFJobLookBackBlocks = ptr.Ptr(500) + config.VRFv2Plus.General.BHFJobPollPeriod = ptr.Ptr(blockchain.StrDuration{Duration: time.Second * 30}) + config.VRFv2Plus.General.BHFJobRunTimeout = ptr.Ptr(blockchain.StrDuration{Duration: time.Minute * 24}) + + newEnvConfig := vrfcommon.NewEnvConfig{ + NodesToCreate: []vrfcommon.VRFNodeType{vrfcommon.VRF, vrfcommon.BHF}, + NumberOfTxKeysToCreate: 0, + UseVRFOwner: false, + UseTestCoordinator: false, + } + + env, vrfContracts, vrfKey, nodeTypeToNodeMap, err = vrfv2plus.SetupVRFV2PlusUniverse( + testcontext.Get(t), t, config, chainID, cleanupFn, newEnvConfig, l) + require.NoError(t, err) + evmClient, err := env.GetEVMClient(chainID) + require.NoError(t, err, "Getting EVM client shouldn't fail") + defaultWalletAddress = evmClient.GetDefaultWallet().Address() + + var isNativeBilling = true + t.Run("BHF Job with complete E2E - wait 256 blocks to see if Rand Request is fulfilled", func(t *testing.T) { + // t.Skip("Skipped since should be run on-demand on live testnet due to long execution time") + configCopy := config.MustCopy().(tc.TestConfig) + // Underfund Subscription + configCopy.VRFv2Plus.General.SubscriptionFundingAmountLink = ptr.Ptr(float64(0)) + configCopy.VRFv2Plus.General.SubscriptionFundingAmountNative = ptr.Ptr(float64(0)) + + consumers, subIDs, err := vrfv2plus.SetupNewConsumersAndSubs( + env, + chainID, + vrfContracts.CoordinatorV2Plus, + configCopy, + vrfContracts.LinkToken, + 1, + 1, + l, + ) + require.NoError(t, err, "error setting up new consumers and subs") + 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) + subIDsForCancellingAfterTest = append(subIDsForCancellingAfterTest, subIDs...) + + _, err = consumers[0].RequestRandomness( + vrfKey.KeyHash, + subID, + *configCopy.VRFv2Plus.General.MinimumConfirmations, + *configCopy.VRFv2Plus.General.CallbackGasLimit, + isNativeBilling, + *configCopy.VRFv2Plus.General.NumberOfWords, + *configCopy.VRFv2Plus.General.RandomnessRequestCountPerRequest, + ) + 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) + //Wait at least 260 blocks + _, err = actions.WaitForBlockNumberToBe(randRequestBlockNumber+uint64(260), evmClient, &wg, time.Second*262, t) + wg.Wait() + require.NoError(t, err) + l.Info().Float64("SubscriptionFundingAmountNative", *configCopy.VRFv2Plus.General.SubscriptionRefundingAmountNative). + Float64("SubscriptionFundingAmountLink", *configCopy.VRFv2Plus.General.SubscriptionRefundingAmountLink). + Msg("Funding subscription") + err = vrfv2plus.FundSubscriptions( + env, + chainID, + big.NewFloat(*configCopy.VRFv2Plus.General.SubscriptionRefundingAmountNative), + big.NewFloat(*configCopy.VRFv2Plus.General.SubscriptionRefundingAmountLink), + vrfContracts.LinkToken, + vrfContracts.CoordinatorV2Plus, + subIDs, + ) + require.NoError(t, err, "error funding subscriptions") + randomWordsFulfilledEvent, err := vrfContracts.CoordinatorV2Plus.WaitForRandomWordsFulfilledEvent( + []*big.Int{subID}, + []*big.Int{randomWordsRequestedEvent.RequestId}, + time.Minute*2, + ) + require.NoError(t, err, "error waiting for randomness fulfilled event") + vrfv2plus.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) + l.Debug().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") + batchBHSTxFound := false + for _, tx := range clNodeTxs.Data { + if strings.EqualFold(tx.Attributes.To, vrfContracts.BatchBHS.Address()) { + batchBHSTxFound = true + } + } + require.True(t, batchBHSTxFound) + + 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") + + l.Info(). + Str("Randomness Request's Blockhash", randomWordsRequestedEvent.Raw.BlockHash.String()). + Str("Block Hash stored by BHS contract", fmt.Sprintf("0x%x", randRequestBlockHash)). + Msg("BHS Contract's stored Blockhash for Randomness Request") + require.Equal(t, 0, randomWordsRequestedEvent.Raw.BlockHash.Cmp(randRequestBlockHash)) + }) +} + func TestVRFv2PlusReplayAfterTimeout(t *testing.T) { t.Parallel() var ( diff --git a/integration-tests/testconfig/README.md b/integration-tests/testconfig/README.md index a86531551ff..fd985c316e2 100644 --- a/integration-tests/testconfig/README.md +++ b/integration-tests/testconfig/README.md @@ -3,6 +3,7 @@ ## Introduction Final implementation has undergone minor adjustments in comparison to the approach by Adam Hamric, Anindita Ghosh, and Sergey Kudasov stated in the ADR. The primary changes are as follows: + * `TEST_LOG_LEVEL` remains an environment variable, pending the release of version 2. * `TEST_TYPE` is also kept as an environment variable to facilitate dynamic configuration selection by some tests. * TOML configuration of Chainlink nodes themselves has not been added, awaiting version 2. @@ -15,6 +16,7 @@ The `testconfig` package serves as a centralized resource for accessing configur ## Configuration and Overrides The order of precedence for overrides is as follows: + * Environment variable `BASE64_CONFIG_OVERRIDE` * File `overrides.toml` * Product-specific file, e.g., `[product_name].toml` @@ -119,6 +121,7 @@ Finally `default.toml` file is envisioned to contain fundamental and universally GitHub workflows in this repository have been updated to dynamically generate and utilize base64-encoded TOML configurations derived from user inputs or environment variables. For local execution or remote Kubernetes runners, users must manually supply certain variables, which cannot be embedded in configuration files due to their sensitive or dynamic nature. Essential variables might include: + * Chainlink image and version * Test duration for specific tests (e.g., load, soak) * Configuration specific to Loki (mandatory for certain tests) @@ -127,19 +130,25 @@ Essential variables might include: For local testing, it is advisable to place these variables in the `overrides.toml` file. For Kubernetes or remote runners, the process involves creating a TOML file with the necessary values, encoding it in base64, and setting the result as the `BASE64_CONFIG_OVERRIDE` environment variable. ## Embeded config + Because Go automatically excludes TOML files during the compilation of binaries, we must take deliberate steps to include our configuration files in the compiled binary. This can be accomplished by using a custom build tag `-o embed`. Implementing this tag will incorporate all the default configurations located in the `./testconfig` folder directly into the binary. Therefore, when executing tests from the binary, you'll only need to supply the `overrides.toml` file. This file should list only the settings you wish to modify; all other configurations will be sourced from the embedded configurations. You can access these embedded configurations [here](.integration-tests/testconfig/configs_embed.go). ## To bear in mind + ### Validation failures + When the system encounters even a single setting related to a specific product or configuration within the configurations, it triggers a comprehensive validation of the entire configuration for that product. This approach is based on the assumption that if any configuration for a given product is specified, the entire set of configurations for that product must be complete and valid. This is particularly crucial when dealing with the `overrides.toml` file, where it's easy to overlook the need to comment out or adjust values when switching between configurations for different products. Essentially, the presence of any specific configuration detail necessitates that all relevant configurations for that product be fully defined and correct to prevent validation errors. ## Possible nil pointers + If no configuration values are set for a product or its logging parameters, the system won't perform validation checks. This can lead to a 'nil pointer exception' error if you attempt to access a configuration property later on. This situation arises because we use pointers to facilitate optional overrides; accessing an unset (nil) pointer will cause an error. To avoid such issues, especially when general validations might not cover every scenario, it's crucial for users to ensure that all necessary configuration options are explicitly set. Additionally, it's highly recommended to implement test-specific validations to confirm that all required values for a particular test are indeed established. This proactive approach helps prevent runtime errors and ensures smooth test execution. ## Contributing + It's crucial to incorporate all new test configuration settings directly into the TOML configuration files, steering clear of using environment variables for this purpose. Our goal is to centralize all configuration details, including examples, within the same package. This approach simplifies the process of understanding the available configuration options and identifying the appropriate values to use for each setting. ## Reusing TestConfig in other projects + To ensure the cleanliness and simplicity of your project's configuration, it's advised against using the `testconfig` code as a direct library in other projects. The reason is that much of this code is tailored specifically to its current application, which might not align with the requirements of your project. Your project might not necessitate any overrides or could perhaps benefit from a simpler configuration approach. However, if you find a need to utilize some methods from this project, the recommended practice is to implement the required interfaces within your project's configuration package, rather than directly copying and pasting code. For instance, if you aim to incorporate a setup action similar to the `SetupVRFV2Environment` for VRFv2, like the one shown below: @@ -164,5 +173,6 @@ func SetupVRFV2Environment( You should not replicate the entire `TestConfig` structure. Instead, create an implementation of the `types.VRFv2TestConfig` interface in your project and use that as the parameter. This approach allows you to maintain a streamlined and focused configuration package in your project. ## Known Issues/Limitations + * Duplicate file names in different locations may lead to unpredictable configurations being selected. * The use of pointer fields for optional configuration elements necessitates careful handling, especially for programmatic modifications, to avoid unintended consequences. The `MustCopy()` function is recommended for creating deep copies of configurations for isolated modifications. Unfortunately some of the custom types are not copied at all, you need to set them manually. It's true for example for `blockchain.StrDuration` type. diff --git a/integration-tests/testconfig/automation/automation.toml b/integration-tests/testconfig/automation/automation.toml index 58b95f9b4cc..c1fec4f1f8a 100644 --- a/integration-tests/testconfig/automation/automation.toml +++ b/integration-tests/testconfig/automation/automation.toml @@ -25,6 +25,9 @@ spec_type="minimum" chainlink_node_log_level="info" use_prometheus=false +[Load.Automation.DataStreams] +enabled=false + [[Load.Automation.Load]] number_of_upkeeps=5 number_of_events = 1 @@ -34,6 +37,8 @@ check_burn_amount = 0 perform_burn_amount = 0 upkeep_gas_limit = 1000000 shared_trigger = false +is_streams_lookup = false +feeds = ["0x000200"] [[Load.Automation.Load]] number_of_upkeeps=5 @@ -44,6 +49,8 @@ check_burn_amount = 0 perform_burn_amount = 0 upkeep_gas_limit = 1000000 shared_trigger = true +is_streams_lookup = false +feeds = ["0x000200"] [Load.Pyroscope] enabled=false \ No newline at end of file diff --git a/integration-tests/testconfig/automation/config.go b/integration-tests/testconfig/automation/config.go index 4431a640d0d..cb70cde2d8f 100644 --- a/integration-tests/testconfig/automation/config.go +++ b/integration-tests/testconfig/automation/config.go @@ -6,8 +6,9 @@ import ( ) type Config struct { - General *General `toml:"General"` - Load []Load `toml:"Load"` + General *General `toml:"General"` + Load []Load `toml:"Load"` + DataStreams *DataStreams `toml:"DataStreams"` } func (c *Config) Validate() error { @@ -23,6 +24,11 @@ func (c *Config) Validate() error { } } } + if c.DataStreams != nil { + if err := c.DataStreams.Validate(); err != nil { + return err + } + } return nil } @@ -65,6 +71,8 @@ type Load struct { PerformBurnAmount *big.Int `toml:"perform_burn_amount"` SharedTrigger *bool `toml:"shared_trigger"` UpkeepGasLimit *uint32 `toml:"upkeep_gas_limit"` + IsStreamsLookup *bool `toml:"is_streams_lookup"` + Feeds []string `toml:"feeds"` } func (c *Load) Validate() error { @@ -86,6 +94,49 @@ func (c *Load) Validate() error { if c.PerformBurnAmount == nil || c.PerformBurnAmount.Cmp(big.NewInt(0)) < 0 { return errors.New("perform_burn_amount must be set to a non-negative integer") } + if c.SharedTrigger == nil { + return errors.New("shared_trigger must be set") + } + if c.UpkeepGasLimit == nil || *c.UpkeepGasLimit < 1 { + return errors.New("upkeep_gas_limit must be set to a positive integer") + } + if c.IsStreamsLookup == nil { + return errors.New("is_streams_lookup must be set") + } + if *c.IsStreamsLookup { + if len(c.Feeds) == 0 { + return errors.New("feeds must be set") + } + } + + return nil +} +type DataStreams struct { + Enabled *bool `toml:"enabled"` + URL *string `toml:"url"` + Username *string `toml:"username"` + Password *string `toml:"password"` + DefaultFeedID *string `toml:"default_feed_id"` +} + +func (c *DataStreams) Validate() error { + if c.Enabled != nil && *c.Enabled { + if c.URL == nil { + return errors.New("data_streams_url must be set") + } + if c.Username == nil { + return errors.New("data_streams_username must be set") + } + if c.Password == nil { + return errors.New("data_streams_password must be set") + } + if c.DefaultFeedID == nil { + return errors.New("data_streams_feed_id must be set") + } + } else { + c.Enabled = new(bool) + *c.Enabled = false + } return nil } diff --git a/integration-tests/testconfig/common/vrf/common.go b/integration-tests/testconfig/common/vrf/common.go index 9b614b33593..97c413207b1 100644 --- a/integration-tests/testconfig/common/vrf/common.go +++ b/integration-tests/testconfig/common/vrf/common.go @@ -177,6 +177,12 @@ type General struct { BHSJobLookBackBlocks *int `toml:"bhs_job_lookback_blocks"` BHSJobPollPeriod *blockchain.StrDuration `toml:"bhs_job_poll_period"` BHSJobRunTimeout *blockchain.StrDuration `toml:"bhs_job_run_timeout"` + + //BHF Job Config + BHFJobWaitBlocks *int `toml:"bhf_job_wait_blocks"` + BHFJobLookBackBlocks *int `toml:"bhf_job_lookback_blocks"` + BHFJobPollPeriod *blockchain.StrDuration `toml:"bhf_job_poll_period"` + BHFJobRunTimeout *blockchain.StrDuration `toml:"bhf_job_run_timeout"` } func (c *General) Validate() error { diff --git a/integration-tests/testconfig/default.toml b/integration-tests/testconfig/default.toml index 7e518c1fbf2..d334eaa3c13 100644 --- a/integration-tests/testconfig/default.toml +++ b/integration-tests/testconfig/default.toml @@ -8,6 +8,8 @@ log_producer_retry_limit=10 [ChainlinkImage] postgres_version="15.6" +image="public.ecr.aws/chainlink/chainlink" +version="2.9.1" [Network] selected_networks=["simulated"] diff --git a/operator_ui/TAG b/operator_ui/TAG index c9093a07542..219daac9dc2 100644 --- a/operator_ui/TAG +++ b/operator_ui/TAG @@ -1 +1 @@ -v0.8.0-a2b54a2 +v0.8.0-d9ef282 diff --git a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar index c3f9b61243b..cb8fba9d59e 100644 --- a/testdata/scripts/node/validate/disk-based-logging-disabled.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-disabled.txtar @@ -369,6 +369,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar index f22bfc0a28f..2b9cc653d6d 100644 --- a/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar +++ b/testdata/scripts/node/validate/disk-based-logging-no-dir.txtar @@ -369,6 +369,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/disk-based-logging.txtar b/testdata/scripts/node/validate/disk-based-logging.txtar index 82663ae7f95..dc679ad7dbb 100644 --- a/testdata/scripts/node/validate/disk-based-logging.txtar +++ b/testdata/scripts/node/validate/disk-based-logging.txtar @@ -369,6 +369,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/invalid.txtar b/testdata/scripts/node/validate/invalid.txtar index e8726baee47..1631ac88cfb 100644 --- a/testdata/scripts/node/validate/invalid.txtar +++ b/testdata/scripts/node/validate/invalid.txtar @@ -359,6 +359,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 diff --git a/testdata/scripts/node/validate/valid.txtar b/testdata/scripts/node/validate/valid.txtar index 657451d42d6..85ac9640363 100644 --- a/testdata/scripts/node/validate/valid.txtar +++ b/testdata/scripts/node/validate/valid.txtar @@ -366,6 +366,7 @@ SelectionMode = 'HighestHead' SyncThreshold = 5 LeaseDuration = '0s' NodeIsSyncingEnabled = false +FinalizedBlockPollInterval = '5s' [EVM.OCR] ContractConfirmations = 4 diff --git a/tools/ci/check_solc_hashes b/tools/ci/check_solc_hashes index 0fe7d091f13..d846591a72b 100755 --- a/tools/ci/check_solc_hashes +++ b/tools/ci/check_solc_hashes @@ -6,39 +6,13 @@ set -e -SOLC_6_6_LOCAL_PATH="$HOME/.solc-select/artifacts/solc-0.6.6/solc-0.6.6" -SOLC_7_6_LOCAL_PATH="$HOME/.solc-select/artifacts/solc-0.7.6/solc-0.7.6" SOLC_8_6_LOCAL_PATH="$HOME/.solc-select/artifacts/solc-0.8.6/solc-0.8.6" -SOLC_8_15_LOCAL_PATH="$HOME/.solc-select/artifacts/solc-0.8.15/solc-0.8.15" - -SOLC_6_6_LOCAL_SHA=`sha256sum -b $SOLC_6_6_LOCAL_PATH | cut -d " " -f1` -SOLC_6_6_EXPECTED_SHA="5d8cd4e0cc02e9946497db68c06d56326a78ff95a21c9265cfedb819a10a539d" - -SOLC_7_6_LOCAL_SHA=`sha256sum -b $SOLC_7_6_LOCAL_PATH | cut -d " " -f1` -SOLC_7_6_EXPECTED_SHA="bd69ea85427bf2f4da74cb426ad951dd78db9dfdd01d791208eccc2d4958a6bb" SOLC_8_6_LOCAL_SHA=`sha256sum -b $SOLC_8_6_LOCAL_PATH | cut -d " " -f1` SOLC_8_6_EXPECTED_SHA="abd5c4f3f262bc3ed7951b968c63f98e83f66d9a5c3568ab306eac49250aec3e" -SOLC_8_15_LOCAL_SHA=`sha256sum -b $SOLC_8_15_LOCAL_PATH | cut -d " " -f1` -SOLC_8_15_EXPECTED_SHA="5189155ce322d57fb75e8518d9b39139627edea4fb25b5f0ebed0391c52e74cc" - -if [ "$SOLC_6_6_LOCAL_SHA" != "$SOLC_6_6_EXPECTED_SHA" ]; then - printf "solc 0.6.6 did not match checksum.\nGot '$SOLC_6_6_LOCAL_SHA'\nExpected '$SOLC_6_6_EXPECTED_SHA']\n" - exit 1 -fi - -if [ "$SOLC_7_6_LOCAL_SHA" != "$SOLC_7_6_EXPECTED_SHA" ]; then - printf "solc 0.7.6 did not match checksum.\nGot '$SOLC_7_6_LOCAL_SHA'\nExpected '$SOLC_7_6_EXPECTED_SHA'\n" - exit 1 -fi - if [ "$SOLC_8_6_LOCAL_SHA" != "$SOLC_8_6_EXPECTED_SHA" ]; then printf "solc 0.8.6 did not match checksum.\nGot '$SOLC_8_6_LOCAL_SHA'\nExpected '$SOLC_8_6_EXPECTED_SHA'\n" exit 1 fi -if [ "$SOLC_8_15_LOCAL_SHA" != "$SOLC_8_15_EXPECTED_SHA" ]; then - printf "solc 0.8.15 did not match checksum.\nGot '$SOLC_8_15_LOCAL_SHA'\nExpected '$SOLC_8_15_EXPECTED_SHA'\n" - exit 1 -fi